Linux内核对网卡收包处理机制大约经历了4个阶段。
1、网卡在同一时刻只能接收一个包,当网卡接收到包之后,马上向中断控制器发出中断请求,中断控制器向CPU发出中断信号。
2、网卡在同一时刻能接收多个包,单CPU,网卡接收到多个包的时刻,马上向中断控制器发出中断请求,中断控制器向CPU发出中断信号。
3、网卡在同一时刻能接收多个包,多CPU,网卡接收到多个包的时刻,马上向中断控制器发出中断请求,中断控制器向CPU发出中断信号,所有CPU都将接收到数据包放入同一个接受队列里。
4、网卡支持多队列+DMA方式,多CPU,网卡接收到多个包的时刻,主动把数据包通过网卡DMA到rx_ring(多个)里,当DMA完成时,发生网卡硬件中断,在硬中断里调用软中断,软中断把该CPU对应的r_ring里buffer拷贝到链路层(又称为接口层)接收队列里。
第一个阶段(约1985~1997?):
tcp/ip协议栈在1985左右开始集成到BSD UNIX内核中。在那个年代,互联网是个稀罕玩意儿,网络流量不大,网卡性能也比较弱。
网络处理机制从纯硬中断到下半部机制过渡。
第二个阶段(约1997~2000?):
网络流量开始增大,传统的Linux下半部机制仍然能应付。
第三个阶段(2000~2008?):
Linux内核开始出现NAPI网络处理机制。
这个阶段最大的问题在于SMP下网卡的优势无法发挥出来。中断落在CPU0上,SMP对网卡处理负载不均衡。流量大的时候,CPU0负载很高,网卡丢包现象严重。
解决问题的方法是采用APIC中断控制器,但是,此时接收队列仍然只有1个,即便网卡中断均衡到多个CPU, 接收队列只有一个 ,CPU对网卡数据处理仍然有很大瓶颈。这好比5个未成年男淫与一个成年女性轮流发生性关系,没办法5个人一起来,只能轮流来。
第四个阶段:(约2008?~now):
多队列网卡出现。同一个网卡具备多个rx_ring和DMA功能。本质上,借用了NUMA架构思想(与SMP同一层级的架构)。