大家好,我是「云舒编程」,今天我们来聊聊Linux是怎么从网络上接收数据包的。
文章首发于公众号:云舒编程
关注公众号获取:
1、大厂项目分享
2、各种技术原理分享
3、部门内推
前言
通过前面的文章我们已经了解了「数据包从HTTP层->TCP层->IP层->网卡->互联网->目的地服务器」这中间涉及的知识。
本文将继续介绍「数据包怎么从网线到进程,在被应用程序使用」。
系列文章
图解 | 深入揭秘数据链路层、物理层工作原理
图解 | 深入揭秘IP层工作原理
图解 | 深入揭秘TCP工作原理
图解 | 深入揭秘HTTP工作原理
图解 | 深入揭秘Linux 接收网络数据包
图解 | 深入揭秘IO多路复用原理
通过本文你可学到:
- Linux 是怎么发送数据包到网络上的
- Linux 是怎么从网络上接收数据包的
- 软中断、硬中断
Linux 是怎么从网络上接收数据包的
整体流程:
- 系统初始化时,网卡驱动程序会向内核申请一块内存「ring buffer」,用于存储未来到达的网络数据包;
- 网卡驱动程序将上一步申请的「ring buffer」地址告诉网卡;
- 当数据包从网络上通过网线到达网卡后,网卡会通过DMA将数据拷贝到ring buffer中(这个过程不需要cpu参与);
- 同时网卡会产生CPU硬中断,告诉CPU现在有数据来了,你必须最高优先级处理,否则数据待会存不下了;
- CPU看到网卡产生的硬中断后,调用对应的网卡驱动硬中断处理程序;
- 网卡驱动被调用后,首先禁用网卡的硬中断,然后启动对应的软中断函数;
- 软中断函数开始从ring buffer中进行循环取包,并且封装为sk_buff,然后投递给网络协议栈进行处理;
- 协议栈处理完成后数据就进入用户态的对应进程,进程就可以操作数据了。
中断
当硬件设备完成属于自己部分的操作后,需要CPU帮忙完成剩下的操作时,它需要有一个机制通知CPU。这个机制就叫中断。
中断本质上是一种特殊的电信号,由硬件设备发向CPU,CPU接收到中断后,会马上向操作系统反映此信号的到来,然后就由操作系统负责处理这些新到来的数据。
不同的硬件设备对应的中断不同,他们通过一个唯一的数字进行区分。因此,操作系统就可以区分中断是来自键盘还是硬盘,还是网卡。这样,操作系统才能给不同的中断提供对应的中断处理程序。
每种类型的中断都对应一个中断程序,当中断发生时,CPU就会找到对应的中断程序然后执行。中断在整个操作系统中拥有最高优先级,当一个中断到来后,CPU必须马上停止当前正在执行的程序,转而执行中断程序。
这里可以发现如果中断程序是一段耗时长的逻辑那么就会导致CPU无法释放,效率低下。为了解决这个问题,于是设计了软中断。那么硬件发出信号,CPU响应我们称为硬中断。
有了软中断后,CPU响应中断的逻辑变为了:硬件发出中断信号,CPU收到后调用对应的中断程序(中断程序必须逻辑简单,耗时短),然后中断程序对硬件进行复位或者禁用中断,然后调用软中断函数进行数据处理,而软中断对应的函数就可以让CPU按照自己的调度策略去执。
❝
Linux设计为硬中断在哪个CPU上被响应,那么软中断也是在这个 CPU 上处理的。如果你发现你的 Linux 软中断 CPU 消耗都集中在一个核 上的话,做法是要把调整硬中断的CPU亲和性,来将硬中断打散到不同的 CPU 核上去。
❞
Linux网卡注册中断
static int __igb_open(struct net_device *netdev, bool resuming)
{
/* 分配多 TX 队列的内存空间 */
err = igb_setup_all_tx_resources(adapter);
/* 分配多 RX 队列的内存空间 */
err = igb_setup_all_rx_resources(adapter);
/* 给网卡配置 RX/TX 队