1.当网卡接收到从网络中发送过来的数据后,网卡会向 CPU 发起一个硬件中断。当 CPU 接收到网卡的硬件中断后,便会调用网卡驱动向内核注册的中断处理服务

2.由于在处理硬件中断服务时会关闭硬件中断,所以在处理硬件中断服务的过程中,如果发生了其他的硬件中断,也不能得到有效的处理,从而导致硬件中断丢失的情况。为了避免这种情况出现,Linux 内核把中断处理分为:中断上半部 和 中断下半部,上半部在关闭中断的情况下进行,而下半部在打开中断的情况下进行。由于中断上半部在关闭中断的情况下进行,所以必须要快速完成,从而避免中断丢失的情况。而中断下半部处理是在打开中断的情况下进行的,所以可以慢慢进行。

收包流程:

IRQ

    |--> napi_schedule

        |--> __napi_schedule

            |--> napi_struct加入poll_list中

                |--> net_rx_action // 软中断

net_rx_action 中会对包的个数,以及软中断处理时间进行限制

    |--> 驱动poll方法

        |--> napi_gro_receive()

            |--> netif_receive_skb()

                |--> __netif_receive_skb()


网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。你可以自己先想一下,这种情况下的上半部和下半部分别负责什么工作呢?

对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。

所以,这两个阶段你也可以这样理解:

  • 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;
  • 而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行。

实际上,上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0

#NAp 
netif_rx() 
NAPI 
napi_schedule() 
raise_softirq_irqoff 
net_rx_action() 
*NAp 
process_backlog() 
netif_receive_skb() 
API

Netif_rx的主要工作就是把接收到的数据包添加到待处理过程中,并且启动网络中的下半部处理
硬中断:  将napi_struct结构体加入poll_queue队列(NAPI软中断队列),此时硬中断被禁用,开始切换到NAPI轮询收包工作模式。

软中断:net_rx_aciton->napi_poll->process_backlog