Linux 系统是如何收发网络包的?(计算机网络)

一、Linux 网络协议栈

如下是TCP/IP四层网络模型,实际上Linux 网络协议栈与它相似

4612b18f676c49849bdbe893240c897a.png

 下图是Linux 网络协议栈

ca32350c57b6402e8d01911cad461b16.png

 二、Linux 接收网络包的流程

1.网卡是计算机里的一个硬件,专门负责接收和发送网络包,当网卡接收到一个网络包后,会通过 DMA (Direct Memory Access,直接内存访问)技术,将网络包写入到指定的内存地址,也就是写入到 Ring Buffer (环形缓冲区),接着就会告诉操作系统这个网络包已经到达。

2.告诉操作系统这个网络包已经到达最简单的一种方式就是触发中断,也就是每当网卡收到一个网络包,就触发一个中断告诉操作系统,但一旦网络包多起来,不停的打断会影响系统的整体效率。

为了解决频繁中断带来的性能开销,Linux 内核在 2.6 版本中引入了 NAPI 机制,它是混合「中断和轮询」的方式来接收网络包,它的核心概念就是不采用中断的方式读取数据,而是首先采用中断唤醒数据接收的服务程序,然后 poll 的方法来轮询数据。

因此,当有网络包到达时,会通过 DMA 技术,将网络包写入到指定的内存地址,接着网卡向 CPU 发起硬件中断,当 CPU 收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数。

硬件中断处理函数会做如下的事情:

  • 需要先「暂时屏蔽中断」,表示已经知道内存中有数据了,告诉网卡下次再收到数据包直接写内存就可以了,不要再通知 CPU 了,这样可以提高效率,避免 CPU 不停的被中断。
  • 接着,发起「软中断」,然后恢复刚才屏蔽的中断。

至此,硬件中断处理函数的工作就已经完成。

(硬件中断处理函数做的事情很少,主要耗时的工作都交给软中断处理函数了。)

3.内核中的 ksoftirqd 线程专门负责软中断的处理,当 ksoftirqd 内核线程收到软中断后,就会来轮询处理数据。

ksoftirqd 线程会从 Ring Buffer 中获取一个数据帧,用 sk_buff (socket_buffer,一种数据结构)表示,从而可以作为一个网络包交给网络协议栈进行逐层处理。

4.首先,会进入到网络接口层,在这一层会检查报文的合法性,如果不合法则丢弃,合法则会找出该网络包的上层协议的类型,比如是 IPv4,还是 IPv6,接着再去掉帧头和帧尾,然后交给网络层。

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

6.传输层取出 TCP 头或 UDP 头,根据四元组「源 IP、目的 IP、源端口、目的端口」 作为标识,找出对应的 Socket,并把数据放到 Socket 的接收缓冲区。

7.最后,应用层程序调用 Socket 接口,将内核的 Socket 接收缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程。

下图左边部分看到网络包接收的流程,右边部分刚好反过来,它是网络包发送的流程。

3ed95fe50f3542f18528387a6f915601.png

 

三、Linux 发送网络包的流程

发包是收包的逆过程。

1.首先,应用程序会调用 Socket 发送数据包的接口,由于这个是系统调用,所以会从用户态陷入到内核态中的 Socket 层,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区

2.接下来,网络协议栈从 Socket 发送缓冲区中取出 sk_buff,并按照 TCP/IP 协议栈从上到下逐层处理。

如果使用的是 TCP 传输协议发送数据,那么先拷贝一个新的 sk_buff 副本 ,这是因为 sk_buff 后续在调用网络层,最后到达网卡发送完成的时候,这个 sk_buff 会被释放掉。而 TCP 协议是支持丢失重传的,在收到对方的 ACK(acknowledgement,代表接收方已接收并理解发送的信息) 之前,这个 sk_buff 不能被删除。所以实际上网卡发送的是 sk_buff 的一个拷贝。

接着,对 sk_buff 填充 TCP 头。

sk_buff 可以表示各个层的数据包,在应用层数据包叫 data,在 TCP 层我们称为 segment,在 IP 层我们叫 packet,在数据链路层称为 frame。

3.然后交给网络层,在网络层里会做这些工作:选取路由(确认下一跳的 IP)、填充 IP 头、netfilter 过滤、对超过 MTU 大小的数据包进行分片。处理完这些工作后会交给网络接口层处理。

4.网络接口层会通过 ARP 协议获得下一跳的 MAC 地址,然后对 sk_buff 填充帧头和帧尾,接着将 sk_buff 放到网卡的发送队列中。

5.这一些工作准备好后,会触发「软中断」告诉网卡驱动程序,这里有新的网络包需要发送,驱动程序会从发送队列中读取 sk_buff,将这个 sk_buff 挂到 RingBuffer 中,接着将 sk_buff 数据映射到网卡可访问的内存 DMA 区域,最后触发真实的发送。

6.当数据发送完成以后,还需要清理内存。发送完成的时候,网卡设备会触发一个硬中断来释放内存,主要是释放 sk_buff 内存和清理 RingBuffer 内存。

最后,当收到这个 TCP 报文的 ACK 应答时,传输层就会释放原始的 sk_buff 。

 

发送网络数据的时候,涉及几次内存拷贝操作?

第一次:调用发送数据的系统调用的时候,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区。

第二次:在使用 TCP 传输协议的情况下,从传输层进入网络层的时候,每一个 sk_buff 都会被克隆一个新的副本出来。副本 sk_buff 会被送往网络层,等它发送完的时候就会释放掉,然后原始的 sk_buff 还保留在传输层,等收到这个数据包的 ACK 时,才会释放原始的 sk_buff 。

第三次:当 IP 层发现 sk_buff 大于 MTU 时才需要进行。会再申请额外的 sk_buff,并将原来的 sk_buff 拷贝为多个小的 sk_buff。

 

总结

1.Linux收包:网卡收到网络包之后会通过 DMA 技术将网络包写入RingBuffer环形缓冲区,接着网卡向 CPU 发起硬件中断,当 CPU 收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数。硬件中断函数先暂时屏蔽中断(下一次就直接写入内存而不通知CPU),再发起软中断,软中断调用ksoftirqd 线程从 Ring Buffer 中获取一个数据帧,用sk_buffer(socket_buffer,一种数据类型)表示,然后由网络协议栈处理,先进入网络接口层,去掉帧头和帧尾,再进入网络层,去掉IP头部,接着进入传输层去掉TCP 头或 UDP 头,根据四元组「源 IP、目的 IP、源端口、目的端口」 作为标识,找出对应的 Socket,并把数据放到 Socket 的接收缓冲区。最后,应用层程序调用 Socket 接口,将缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程。

 

2.Linux发包:应用程序会调用 Socket 发送数据包的接口,内核会申请一个 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区,然后网络协议栈从 Socket 发送缓冲区中取出 sk_buff,先进入传输层,如果使用的是 TCP 协议发送数据,会先拷贝一个sk_buff 副本 ,然后为副本TCP头部,本来的sk_buff就留在传输层,接着sk_buff副本在网络层添加上IP头部,然后在网络接口层添加上MAC头部以及帧头和帧尾,最后将 sk_buff 放到网卡的发送队列中。随后会触发「软中断」告诉网卡驱动程序,驱动程序会从发送队列中读取 sk_buff,将这个 sk_buff 挂到 RingBuffer 中,接着将 sk_buff 数据映射到网卡可访问的内存 DMA 区域,最后触发真实的发送。当数据发送完成以后,网卡会触发一个硬中断来释放内存,主要是释放 sk_buff 内存和清理 RingBuffer 内存。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/190136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

15、 深度学习之正向传播和反向传播

上一节介绍了训练和推理的概念,这一节接着训练和推理的概念讲一下,神经网络的正向传播和反向传播。 其实单看正向传播和反向传播这两个概念,很好理解。 正向传播(Forward Propagation)是指从输入层到输出层的数据流动过程,而反向传播(Backpropagation)是指数据从输出…

国际语音群呼系统

随着海外电话营销的发展,越来越多的出海企业通过国际语音群呼系统打开出海营销之路。企业出海营销运营,选择一个安全、高效、便捷的国际语音群呼系统非常重要。 一、什么是国际语音群呼系统? 国际语音群呼是指通过语音的方式批量向海外用户传…

如何使用 NFTScan NFT API 在 Starknet 网络上开发 Web3 应用

Starknet 是由以色列软件公司 StarkWare 开发的免许可的第 2 层网络。Starknet 作为以太坊上的 ZK Rollup 运行,帮助 dApp 使用 STARK 证明以更低的交易成本实现更大的计算规模。该网络允许智能合约与区块链上部署的其他合约进行交互,从而提高协议之间的…

drawio画图工具的四种使用方式

1、免安装使用(绿色版) 这种直接下载下来直接就可以使用,属于绿色版(开箱即用),适用于个人 点击下载地址 2、 安装使用 这种下载下来就需要安装才可使用,适用于个人 点击下载地址 3、war包…

用100ask 6ull配合 飞凌 elf1的教程进行学习的记录

启动方式 百问网 elf1: 固件 emmc-otg 串口 网络 改eth0, 网线接在右边的网口eth2上

【高效开发工具系列】驼峰下划线互转

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

大数据技术之Oozie

大数据技术之Oozie 第1章 Oozie简介 Oozie英文翻译为:驯象人。一个基于工作流引擎的开源框架,由Cloudera公司贡献给Apache,提供对Hadoop MapReduce、Pig Jobs的任务调度与协调。Oozie需要部署到Java Servlet容器中运行。主要用于定时调度任…

NSDT场景编辑器实现真数字孪生

在线工具推荐: 三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数据生成器 - 3D模型在线转换 - 3D模型预览图生成服务 1、什么是数字孪生? 数字孪生是资产或系统的实时虚拟模型,它使用来自连…

spring boot 整合 spring security

项目结构 添加依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.9.RELEASE</version><relativePath/></parent><dependency><grou…

UiPath:人工智能和重新加速增长是 2024 年的好兆头

UiPath&#xff08;NYSE&#xff1a;PATH&#xff09;重新加速增长&#xff0c;同时在销售和营销方面变得最高效&#xff0c;使其成为进入 2024 年的有吸引力的成长型股票。 UiPath 最初被归类为机器人流程自动化 (RPA) 公司&#xff0c;现在认为自己是一家人工智能驱动的自动…

MATLAB R2022b 安装

文章用于学习记录 文章目录 前言下载解压安装包总结 前言 下载解压安装包 MATLAB R2022b —— A9z3 装载(Mount) MATLAB_R2022b_Win64.iso 打开装载好的 DVD 驱动器并找到 setup&#xff0c;单击鼠标右键以管理员身份运行&#xff1a; 点击窗口右上角的 高级选项下拉框&#…

【UGUI】Unity为下拉菜单添加选项(DropDown)

要想控制谁就把谁拿到代码里-获取组件-修改组件参数&#xff08;变量或者方法&#xff09; 代码示例&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro;public class UIcontrol : MonoBehavi…

贝叶斯网络 (期末复习)

文章目录 贝叶斯网络&#xff08;概率图模型&#xff09;定义主要考点例题- 要求画出贝叶斯网络图- 计算各节点的条件概率表- 计算概率-分析独立性 贝叶斯网络&#xff08;概率图模型&#xff09; 定义 一种简单的用于表示变量之间条件独立性的有向无环图&#xff08;DAG&…

一线大厂Redis高并发缓存架构(待完善)

场景1&#xff1a;秒杀库存场景&#xff0c; 10000人抢100个商品 如果用普通的分布式锁实现&#xff0c; 最后抢到的人&#xff0c;要等前面99个人抢完 优化方案&#xff1a;可用分段锁&#xff0c; 降低锁的粒度&#xff0c; 比如1-10库存用锁product:101_1,11-20库存用锁pr…

MySQL -DDL 及表类型

DDL 创建数据库 CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...] create_specification:[DEFAULT] CHARACTER SET charset_name [DEFAULT] COLLATE collation_name 1.CHARACTER SET&#xff1a…

PT读spef报PARA-006如何解决?

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 There are multiple causes that can trigger PARA-006 errors. Here is a checklist. 1) SPEF reading order Functionally, the parasitic files can be read in any order. For best stitching…

acwing算法基础之动态规划--数位统计DP、状态压缩DP、树形DP和记忆化搜索

目录 1 基础知识2 模板3 工程化 1 基础知识 暂无。。。 2 模板 暂无。。。 3 工程化 题目1&#xff1a;求a~b中数字0、数字1、…、数字9出现的次数。 思路&#xff1a;先计算1~a中每位数字出现的次数&#xff0c;然后计算1~b-1中每位数字出现的次数&#xff0c;两个相减即…

C++基础 -29- 友元类

友元类格式 friend class person2;类的友元类访问类的全部成员 #include "iostream"using namespace std;class person1 { public:int a;protected:int b;private:int c;friend class person2; };class person2 { public:void test(){person1 a;a.a 100;a.b 200…

校园局域网规划与设计(cisco仿真模拟)

摘 要 随着网络技术的发展&#xff0c;校园网的建设已经进入到一个蓬勃发展的阶段。校园网的建成和使用&#xff0c;对于提高教学和科研的质量、改善教学和科研条件、加快学校的信息化进程&#xff0c;开展多媒体教学与研究以及使教学多出人才、科研多出成果有着十分重要而深远…

05-建造者模式-C语言实现

UML类图&#xff1a; 代码实现&#xff1a; #include <stdio.h> #include <stdlib.h>// 产品类 typedef struct {char* part1;char* part2;char* part3; } Product;// 抽象建造者类 typedef struct {void (*buildPart1)(void*, const char*);void (*buildPart2)(v…