##summary
softirq 真正干活的函数是__do_softirq
。
linuxv3.11内核里能够执行__do_softirq
,有如下调用,
这里指真正执行softirq的地方,不是触发(设置)softirq标志 !!!
- 每个硬中断退出的时。
- 当bh使能的时。
- 发送回环报文时。
case1 每个硬中断退出的时候。
call trace
1 | > irq_exit |
irq_exit
1 | 350 /* |
invoke_softirq
1 | 329 static inline void invoke_softirq(void) |
case2 使能bh的时候
call trace
1 | > local_bh_enable |
local_bh_enable
1 | 184 void local_bh_enable(void) |
_local_bh_enable_ip
NOTE: 使能bh的时候,刚开始抢占还是禁止的。只有软中断处理完了后,抢占才使能的。
顺便说一下,使能bh时,有可能发生进程切换(见preempt_check_resched
).
1 | 157 static inline void _local_bh_enable_ip(unsigned long ip) |
do_softirq
根据不同的体系机构有不同的版本。
当对应的硬件体系里没有定义do_softirq
时,使用kernel/softirq.c
中通用的do_softirq`.
1 | 286 |
而对于X86_64,有其自己的定义。
1 | 92 extern void call_softirq(void); |
其中call_softirq
是个用汇编语言写的一个函数定义在 arch/x86/kernel/entry_64.S
netif_rx_ni
这一块的理解不是很透,仅以一个具体的例子来说明。发送回环报文
.
发送回环报文
call trace
1 | > dev_loopback_xmit |
loopback 报文会通过netif_rx
函数,被重新放回到
per_cpu变量softnet_data
下的队列input_pkt_queue
里,
同时激发napi调用,进而激发软中断调用(只是设置标志位,不是真正调用)
另外,注意netif_rx_ni
里没有禁止bh调度,而是只是禁止了抢占(preempt_disable
).
dev_loopback_xmit
1 | 2765 int dev_loopback_xmit(struct sk_buff *skb) |
netif_rx_ni
1 | 3267 int netif_rx_ni(struct sk_buff *skb) |