飞道的博客

深入理解Linux网络:第二章-内核是怎么接收数据包的?

277人阅读  评论(0)

关于中断

内核和网络设备驱动都是通过中断的方式来处理的。

当然中断分为两种,硬中断和软中断。当设备有数据进来了,设备首先会触发硬中断,因为处理数据需要耗费很长的时间所以CPU肯定是要把耗时的事情交给别人去干,随后CPU会发出软中断,让内核线程去处理数据。

两种中断的触发方式,硬中断通过给CPU相关的引脚发出一个电压变化,软中断通过一个内存里面的变量来做一个标记。同时程序里面说的那种都是软中断。他只是一个标记不会真的,意思是当前线程需要让出CPU资源。

内核收到路径

  1. 数据帧从外部网络到达网卡
  2. 网卡把帧DMA到内存上(RingBuffer)
  3. 网卡硬中断通知CPU
  4. CPU 响应硬中断,建立处理后发出软中断给内核线程
  5. 内核线程处理软中断,开始调用网卡驱动注册的poll函数开始收包
  6. 内核线程把数据从RingBuffer 上摘下来 保存为一个skb (网络协议栈数据结构体)
  7. 协议层开始处理网络帧,处理完成后数据data被放到socket的接收队列中。 (处理 :主要是传输层的一些处理,会根据不同的协议包来处理 拆包 封包等等)
  8. 内核唤醒用户进程

标记:这里最好结合计算机网络模型一起看

RingBuffer

RingBuffer 由三部分组成 igb_rx_buffer (这个数组是内核使用的), e1000_adv_rx_desc 数组(这个数组是网卡硬件使用的), skb (网络帧数据结构体)。

RingBuffer 是有大小的。

RingBuffer 当然也分为RX TX 两种,RX:接收数据队列,TX:发送数据队列

RingBuffer 丢数据的情况?

当RingBuffer 满的时候,新来的数据包就会被丢弃。使用ifconfig命令查看网卡的时候,可以看到里面有一个overruns,表示因为RingBuffer 队列满被丢弃的包数,如果发现有 丢包,可以通过ethtool 命令来加大环形队列的长度。

为什么网卡开启多队列能提升网络性能?

每一个队列都有独立的、不同的中断好,所以不同的队列在将数据接收到自己的 RingBuffer 后,会想不同的CPU 发起硬中断通知,而在硬中断处理中,软中断的执行是基于当前CPU核来执行的。所以如果只有一个队列的话,那么每一次处理数据都是由同一个CPU在执行。需要开启多队列,让不同的CPU来处理网络数据接收。


转载:https://blog.csdn.net/qq_40261771/article/details/128526755
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场