linux内核⽹络协议栈越来越多的被关注,因为⽹络流量发⽣的巨⼤的变化,每⼩时的流量相当于过去⼏天的流量。linux内核⽹络协议栈的性能本⾝就不好,⼀些内核协议栈的实现瓶颈被发现,因此即使10GE的⽹卡⼤量投⼊使⽤也没有带来预期的性能提升。
因此⼀些跳过内核来处理⽹络包的技术⼿段应允⽽⽣,主要⽬的是为了实现低延迟,低消耗,⾼吞吐的⽹络,典型代表是DPDK。 那么DPDK是如何处理报⽂的呢?
在说明这个问题之前,我们先描述下linux内核的协议栈实现。 Linux内核收包处理流程:
- 1,当⽹卡收到报⽂后,通过DMA机制将报⽂放到内存
- 2,⽹卡触发中断通知系统有报⽂到达(⼀个报⽂,⼀个中断),系统分配sk_buff,将报⽂copy到这块sk_buff中,然后交由协议栈处理
- 3,经过协议栈处理,将报⽂上送⽤户态应⽤程序处理从上⾯的简单描述可以看出,处理越多报⽂就消耗越多资源(中断,内存等)
-
a.⼀个报⽂⼀个中断,中断将打断CPU并且涉及上下⽂切换,将消耗系统资源
-
b.每个报⽂都要分配sk_buff,申请分配将消耗很多资源,同时linux为了兼容很多协议将sk_buff设计的过于复杂和庞⼤,导致处理变得缓慢。
-
c.其次,当⽤户态程序需要收发包时涉及多次系统调⽤和上下⽂切换,这些切换将消耗⼤量的系统资源。
为了解决a/b问题,Linux在2.6版本开始⽀持NAPI,⼤体原理如下:⽹卡⾸先⼯作在中断模式,⾸包到达后中断处理程序处理报⽂,然后关闭⽹卡中断然后进⼊轮询模式,轮询检查⽹卡收包队列然后收包。其中轮询模式处理函数由⽹卡驱动实现,初始化过程中挂接即可。 DPDK如何解决这些问题