(内容主要来自“深入理解Linux网络内幕”一书)
数据包接收可以分为两部分:
1. 驱动
* 驱动将frame拷贝到sk_buff,然后放入input queue。这里是中断context,可以抢占第二部分(kernel部分)。
* 通过调度NET_RX_SOFTIRQ通知内核有新frame需要处理。
2. Kernel
Kernel处理input queue。
一次中断,多个Frame:
为提高性能,驱动可以持续拷贝frame到input queue,直到指定数量或超过指定时间。例如3c59x.c中vortex_interrupt()函数。
这是驱动自己的事情。
注意:当中断被禁止时,设备在自己的寄存器中保持到来的中断。
NAPI:
驱动 disable 某个有frame到达设备的中断,并让kernel polling驱动的队列。
中断处理程序:
中断处理程序不可抢占(当中断处理程序处理完必要的数据后,会打开本地中断;这样的话,本中断可以被优先级更高的硬中断中断),也不可重入。这样简化了中断处理程序的编写。
当一个给定的中断处理程序正在执行时,相应的中断线在所有处理器上都会被屏蔽掉,以防止在同一中断线上接收另一个新的中断。 通常情况下,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断线总是被禁止的。
所以中断处理程序必须快,而且只做与硬件有关的操作。例如接收数据包的中断处理,只需要创建sk_buff,把数据从网卡copy到sk_buff即可;后续的操作由softirq完成。
Softirq (BH):