linux网卡驱动中断,深入理解Linux网络技术内幕-中断和网络驱动程序(三)

softirq函数是通过open_softirq函数注册的,其实就是在一个全局数据中设置对应的执行函数:

struct softirq_action

{

void    (*action)(struct softirq_action *);

};

static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

void open_softirq(int nr, void (*action)(struct softirq_action *))

{

softirq_vec[nr].action = action;}

与softirq调度相关的函数包括:

__raise_softirq_irqoff:设置要执行的软softirq相关联的位标识,稍后检查这个标识,相关联的函数就会被调用。

static inline void __raise_softirq_irqoff(unsigned int nr)

{

trace_softirq_raise(nr);

or_softirq_pending(1UL << nr);}

#define or_softirq_pending(x)  (local_softirq_pending() |= (x)) //位与上相关位,在当前CPU的变量上设置,谁触发谁执行机制

raise_softirq_irqoff:对__raise_softirq_irqoff函数进行调用封装,然后检查当前函数是不是从硬件或软件中断环境中调用,若不是则唤醒ksoftirqd线程(每个CPU都有自己的ksoftirqd内核线程),执行softirq。若是则不需要调用此线程,因为从中断中返回会调用do_softirq函数。

inline void raise_softirq_irqoff(unsigned int nr)

{

__raise_softirq_irqoff(nr);

/*

* If we're in an interrupt or softirq, we're done

* (this also catches softirq-disabled code). We will

* actually run the softirq once we return from

* the irq or softirq.

*

* Otherwise we wake up ksoftirqd to make sure we

* schedule the softirq soon.

*/

if (!in_interrupt())

wakeup_softirqd();

}

static void wakeup_softirqd(void)

{

/* Interrupts are disabled: no need to stop preemption */

struct task_struct *tsk = __this_cpu_read(ksoftirqd);

if (tsk && tsk->state != TASK_RUNNING)

wake_up_process(tsk);

}

raise_softirq:对raise_softirq_irqoff函数的封装调用,但执行时会关闭中断功能。

void raise_softirq(unsigned int nr)

{

unsigned long flags;

local_irq_save(flags);

raise_softirq_irqoff(nr);

local_irq_restore(flags);

}

softirq调用会被执行的地点出了主动触发和ksoftirqd内核线程调度外,还包括:

irq_exit:从中断返回时。

/*

* Exit an interrupt context. Process softirqs if needed and possible:

*/

void irq_exit(void)

{

account_system_vtime(current);

trace_hardirq_exit(); //退出中断

sub_preempt_count(IRQ_EXIT_OFFSET);

if (!in_interrupt() && local_softirq_pending())

invoke_softirq();

rcu_irq_exit();

#ifdef CONFIG_NO_HZ

/* Make sure that timer wheel updates are propagated */

if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())

tick_nohz_stop_sched_tick(0);

#endif

preempt_enable_no_resched();//打开可抢占}

static inline void invoke_softirq(void)

{

if (!force_irqthreads)

do_softirq();

else

wakeup_softirqd();

}

在netif_rx_ni函数中也会调用softirq:

int netif_rx_ni(struct sk_buff *skb)

{

int err;

preempt_disable(); //关闭可抢占

err = netif_rx(skb);

if (local_softirq_pending())

do_softirq();    preempt_enable();  //打卡可抢占

return err;

}

EXPORT_SYMBOL(netif_rx_ni);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值