首页 > 社交 > 科普中国

25

常驻编辑 科普中国 2022-06-02 子系统   网络   队列   内核   网卡   函数   源码   内存   过程   数据   用户

在开始今天的文章之前,我先来请大家思考几个小问题。gEf拜客生活常识网

  • 问1:我们在查看内核发送数据消耗的 CPU 时,是应该看 sy 还是 si ?
  • 问2:为什么你服务器上的 /proc/softirqs 里 NET_RX 要比 NET_TX 大的多的多?
  • 问3:发送网络数据的时候都涉及到哪些内存拷贝操作?

这些问题虽然在线上经常看到,但我们似乎很少去深究。如果真的能透彻地把这些问题理解到位,我们对性能的掌控能力将会变得更强。gEf拜客生活常识网

带着这三个问题,我们开始今天对 Linux 内核网络发送过程的深度剖析。还是按照我们之前的传统,先从一段简单的代码作为切入。如下代码是一个典型服务器程序的典型的缩微代码:gEf拜客生活常识网

int main(){  
 fd = socket(AF_INET, SOCK_STREAM, 0);  
 bind(fd, ...);  
 listen(fd, ...);  
  
 cfd = accept(fd, ...);  
  
 // 接收用户请求  
 read(cfd, ...);  
  
 // 用户请求处理  
 dosometing();   
  
 // 给用户返回结果  
 send(cfd, buf, sizeof(buf), 0);  
}  

今天我们来讨论上述代码中,调用 send 之后内核是怎么样把数据包发送出去的。本文基于Linux 3.10,网卡驱动采用Intel的igb网卡举例。gEf拜客生活常识网

预警:本文共有一万多字,25 张图,长文慎入!gEf拜客生活常识网

一、Linux 网络发送过程总览

我觉得看 Linux 源码最重要的是得有整体上的把握,而不是一开始就陷入各种细节。gEf拜客生活常识网

我这里先给大家准备了一个总的流程图,简单阐述下 send 发送了的数据是如何一步一步被发送到网卡的。gEf拜客生活常识网

gEf拜客生活常识网

在这幅图中,我们看到用户数据被拷贝到内核态,然后经过协议栈处理后进入到了 RingBuffer 中。随后网卡驱动真正将数据发送了出去。当发送完成的时候,是通过硬中断来通知 CPU,然后清理 RingBuffer。gEf拜客生活常识网

因为文章后面要进入源码,所以我们再从源码的角度给出一个流程图。gEf拜客生活常识网

gEf拜客生活常识网

虽然数据这时已经发送完毕,但是其实还有一件重要的事情没有做,那就是释放缓存队列等内存。gEf拜客生活常识网

那内核是如何知道什么时候才能释放内存的呢,当然是等网络发送完毕之后。网卡在发送完毕的时候,会给 CPU 发送一个硬中断来通知 CPU。更完整的流程看图:gEf拜客生活常识网

gEf拜客生活常识网

注意,我们今天的主题虽然是发送数据,但是硬中断最终触发的软中断却是 NET_RX_SOFTIRQ,而并不是 NET_TX_SOFTIRQ !!!(T 是 transmit 的缩写,R 表示 receive)gEf拜客生活常识网

意不意外,惊不惊喜???gEf拜客生活常识网

所以这就是开篇问题 1 的一部分的原因(注意,这只是一部分原因)。

相关阅读:

  • 量子子系统的新理论
  • 无法检验的科学是科学吗?
  • 伊朗成功发射太空拖船“萨曼轨道传输器”
  • HUAWEI
  • 纳莱迪人儿童遗骸发现谜团重重
  • 并不是所有的物联网平台都适合系统集成
  • 网络销售怎么去聊客户(网络销售出单难吗)
  • 多益网络怎么样(广州多益网络工作感受)
  • 网络短视频内容审核标准细则发布:短视频节目不得未经
  • 移动网络怎么样(移动300兆相当于电信多少兆)
    • 网站地图 |
    • 声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不做权威认证,如若验证其真实性,请咨询相关权威专业人士。