一口Linux

电子技术应用专栏作家——一口Linux。一起学习嵌入式、Linux、网络、驱动、arm知识

Linux 网络收包流程

0
阅读(1741)

  我们在跟别人网上聊天的时候,有没有想过你发送的信息是怎么传到对方的电脑上的

  又或者我们在上网冲浪的时候,有没有想过 HTML 页面是怎么显示在我们的电脑屏幕上的

  无论是我们跟别人聊天还是上网冲浪,其实都依靠于计算机网络这项技术

  计算机网络是指将多台计算机通过通信设备和传输介质连接在一起,使得它们之间能够相互通信、资源共享和协同工作

  而计算机之间是通过数据包来实现信息传输和信息交换的,数据包是计算机网络中传输数据的基本单位

  今天咸鱼将以 Linux 为例来给大家介绍一下 Linux 是如何实现网络接收数据包

  网络协议栈&网络架构

  在正文开始之前,我们先来了解一下 Linux 中的网络协议模型和网络子系统

  •   网络协议模型(网络协议栈)

  在 Linux 中,Linux 网络协议栈分成了五层

image.png

  其中:

  •   应用层提供 socket 接口来供用户进程访问内核空间的网络协议栈

  •   传输层、网络层协议由 Linux 内核网络协议栈实现

  •   链路层协议靠网卡驱动来实现

  •   物理层协议由硬件网卡实现

image.png

  •   网络子系统(网络架构)

  网络子系统是 Linux 内核中的一部分,由多个模块和驱动程序组成,它负责管理和控制系统的网络功能以实现网络通信

  通过 Linux 网络子系统(网络架构)来实现上述网络协议模型

image.png

  其中

  •   System call interface:为应用程序获取内核的网络系统提供了接口,例如 socket

  •   Protocol agnostic interface:为和各种传输层协议的网络交互提供的一层公共接口

  •   Network protocals:对各种传输层协议的实现,如 TCP、UDP、IP 等

  •   Device agnostic interface:为各种底层网络设备抽象出的公共接口,与各种网络设备驱动连接在一起

  •   Device drivers:与各种网络设备交互的驱动

  收包过程

  当 Linux 接收一个数据包的时候,这个包是怎么经过 Linux 的内核从而被应用程序拿到的呢?

  image.png

  •   到达网卡(NIC,Network Interface Card)

  首先数据包到达网卡之后,网卡会校验接收到的数据包中的目的 MAC 地址是不是自己的 MAC 地址,如果不是的话通常就会丢弃掉

  这种只接受发送给自己的数据包(其余的扔掉)的工作模式称为非混杂模式(Non-Promiscuous Mode)

  混杂模式(Promiscuous Mode)则是网卡会接收通过网络传输的所有数据包,而不仅仅是发送给它自己的数据包

  非混杂模式是网卡默认的工作模式,可以尽可能的保护网络安全和减少网络负载

  网卡在校验完 MAC 地址之后还会校验数据帧(Data Frame)中校验字段 FCS 来一次确保接收到的数据包是正确的

  •   网卡硬件缓冲区 ——> 系统内存(ring buffer)

  当网卡接收到数据包时,它将数据包的内容存储在硬件缓冲区中,然后通过 DMA 将接收到的数据从硬件缓冲区传输到系统内存中的指定位置,这个位置通常是一个环形缓冲区( ring buffer)

  DMA(直接内存访问,Direct Memory Access)

  DMA是一种数据传输技术,允许外设(如网卡、硬盘控制器、显卡等)直接访问计算机内存,而无需经过 CPU

  通过 DMA 可以大大提高数据传输的效率,减轻 CPU 的负担

  •   触发硬中断

  当网卡将数据包 DMA 到用于接收的环形缓冲区(rx_ring)之后,就会触发一个硬中断来告诉 CPU 数据包收到了

  什么时候会触发一个硬中断,可以通过下面的参数来进行配置:

  •   rx-usecs:当过这么长时间过后,一个中断就会被产生

  •   rx-frames:当累计接收到这么多个数据帧后,一个中断就会被产生

  上面的参数配置可以通过下面的命令来查看

 image.png

  image.png

  image.png  image.png

  总结

  网络模块可以说是 Linux 内核中最复杂的模块了

  看起来一个简简单单的收包过程就涉及到许多内核组件之间的交互,如网卡驱动、协议栈,内核ksoftirqd 线程等

  咸鱼原本打算把收包和发包的流程都写上的,但是光是写收包流程就就要了我半条命了,等下次有机会把发包的流程也写一下

  总结一下 Linux 网络收包流程:

  •   数据到达网卡之后,网卡通过 DMA 将数据放到内存分配好的一块 ring buffer 中,然后触发硬中断

  •   CPU 收到硬中断之后简单的处理了一下(分配 skb_buffer),然后触发软中断

  •   软中断进程 ksoftirqd 执行一系列操作(例如把数据帧从 ring ruffer上取下来)然后将数据送到三层协议栈中

  •   在三层协议栈中数据被进一步处理发送到四层协议栈

  •   在四层协议栈中,数据会从内核拷贝到用户空间,供应用程序读取

  •   最后被处在应用层的应用程序去读取

原文链接:https://mp.weixin.qq.com/s/GqEdfE1fJI5t8ZQ_0Bj-Ww

微信图片_20220701092006.jpg

电子技术应用专栏作家  一口Linux