Linux 网络包收发流程

介绍

在 Linux 操作系统中,网络包的收发涉及到一系列复杂而精密的处理步骤,以确保数据的可靠传输和系统的安全运行。从网络数据包进入网卡开始,到最终被应用程序处理,这个过程穿越了多个层次的网络协议栈,每一步都经过了精心设计和优化,以应对各种网络环境和应用场景的需求。

网络包的接收流程

  • 第一步:当一个网络帧到达网卡后,网卡会通过 DMA 方式,把这个网络包放到收包队列中;然后通过硬中断,告诉中断处理程序已经收到了网络包。

    DMA,全称 Direct Memory Access,即直接存储器访问。DMA 传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实现和完成的。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为 RAM 和 IO 设备开辟一条直接传输数据的通道,使得 CPU 的效率大大提高。

  • 第二步:网卡中断处理程序会为网络帧分配内核数据结构(sk_buff),并将其拷贝到 sk_buff 缓冲区中;然后再通过软中断,通知内核收到了新的网络帧。

    sk_buff 是 Linux 内核网络子系统中的一个结构体,用于表示网络数据包的缓冲区。它在网络协议栈中扮演了重要的角色,包含了数据包的各种信息,比如数据内容、协议头部等。在 Linux 内核中,sk_buff 被广泛用于处理网络数据包的接收和发送,提供了一种方便的方式来操作和管理数据包。

  • 第三步:内核协议栈从缓冲区中取出网络帧,并通过网络协议栈,从下到上逐层处理这个网络帧:

    1. 在链路层检查报文的合法性,找出上层协议的类型(比如 IPv4 还是 IPv6),再去掉帧头、帧尾,然后交给网络层。

    2. 网络层取出 IP 头,判断网络包下一步的走向,比如是交给上层处理还是转发。当网络层确认这个包是要发送到本机后,就会取出上层协议的类型(比如 TCP 还是 UDP),去掉 IP 头,再交给传输层处理。

    3. 传输层取出 TCP 头或者 UDP 头后,根据 < 源 IP、源端口、目的 IP、目的端口 > 四元组作为标识,找出对应的 Socket,并把数据拷贝到 Socket 的接收缓存中。

  • 最后,应用程序就可以使用 Socket 接口,读取到新接收到的数据了。

网络包的发送流程

了解网络包的接收流程后,就很容易理解网络包的发送流程。网络包的发送流程就是上图的右半部分,很容易发现,网络包的发送方向,正好跟接收方向相反。

首先,应用程序调用 Socket API(比如 sendmsg)发送网络包。

由于这是一个系统调用,所以会陷入到内核态的套接字层中。套接字层会把数据包放到 Socket 发送缓冲区中。

接下来,网络协议栈从 Socket 发送缓冲区中,取出数据包;再按照 TCP/IP 栈,从上到下逐层处理。比如,传输层和网络层,分别为其增加 TCP 头和 IP 头,执行路由查找确认下一跳的 IP,并按照 MTU 大小进行分片。

分片后的网络包,再送到网络接口层,进行物理地址寻址,以找到下一跳的 MAC 地址。然后添加帧头和帧尾,放到发包队列中。这一切完成后,会有软中断通知驱动程序:发包队列中有新的网络帧需要发送。

小结

  1. 内核分配一个主内存地址段(DMA 缓冲区),网卡设备可以在 DMA 缓冲区中读写数据

  2. 当来了一个网络包,网卡将网络包写入 DMA 缓冲区,写完后通知 CPU 产生硬中断

  3. 硬中断处理程序锁定当前 DMA 缓冲区,然后将网络包拷贝到另一块内存区,清空并解锁当前 DMA 缓冲区,然后通知软中断去处理网络包。

发送数据包与上述相反,链路层将数据包封装完毕后,放入网卡的 DMA 缓冲区,并调用系统硬中断,通知网卡从缓冲区读取并发送数据。

参考:

!

posted @   lttL  阅读(316)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示