Linux 系统是如何收发网络包的?

news2024/11/18 9:30:50

一、Linux 网络协议栈

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

 下图是Linux 网络协议栈

 二、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 接收缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程。

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

三、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.coloradmin.cn/o/1276362.html

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

相关文章

如何快速了解一家公司?

在炒股过程中,我们想要了解一家公司是否具有投资价值,需要查看和阅读很多公司的相关资料。股民们自行去查询往往会花费很多的时间精力,所以专业的炒股软件一般都会给股民提供这些现成的资料。 在金斗云智投APP内,进入到个股详情页…

SCA技术进阶系列(四):DSDX SBOM供应链安全应用实践

一、SBOM的发展趋势 数字时代,软件已经成为维持生产生活正常运行的必备要素之一。随着容器、中间件、微服务、 DevOps等技术理念的演进,软件行业快速发展,但同时带来软件设计开发复杂度不断提升,软件供应链愈发复杂,软…

28.线段树与树状数组基础

一、线段树 1.区间问题 线段树是一种在算法竞赛中常用来维护区间的数据结构。它思想非常简单,就是借助二叉树的结构进行分治,但它的功能却非常强大,因此在很多类型的题目中都有它的变种,很多题目都需要以线段树为基础进行发展。…

Windows server 2016 FTP服务器的搭建

FTP(File Transfer Protocol)是一个用来在两台计算机之间传输文件的通信协议。这两台计算机中,一台是FTP服务器,另一台是FTP 客户端。 1.安装FTP服务与建立FTP站点 1.1 打开服务器管理器——单击仪表盘的添加角色和功能 1.2 持续…

Gavin Wood:财库保守主义偏离了初心,应探索 Fellowship 等更有效的资金部署机制

波卡创始人 Gavin Wood 博士最近接受了 The Kusamarian 的采访,分享了他的过往经历、对治理的看法,还聊到了 AI、以太坊、女巫攻击、财库等话题。本文整理自 PolkaWorld 对专访编译的部分内容,主要包含了 Gavin 对治理、财库提案、生态资金分…

听GPT 讲Rust源代码--src/tools(4)

题图由AI生成 File: rust/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs 在Rust源代码中,rust/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs这个文件是rust-analyzer工具的一部分,它定义了用于将类型系统中的实体进行唯一标识和共享…

15.oracle的 listagg() WITHIN GROUP () 行转列函数使用

1.使用条件查询 查询部门为20的员工列表 -- 查询部门为20的员工列表 SELECT t.DEPTNO,t.ENAME FROM SCOTT.EMP t where t.DEPTNO 20 ; 效果: 2.使用 listagg() WITHIN GROUP () 将多行合并成一行(比较常用) SELECT T .DEPTNO, listagg (T .ENAME, ,) WIT…

uniapp小程序分包页面引入wxcomponents(vue.config.js、copy-webpack-plugin)

实例:小程序添加一个源生小程序插件,按照uniapp官方的说明,要放在wxcomponents。后来发现小程序超2m上传不了。 正常的编译情况 会被编译到主包下 思路:把wxcomponents给编译到分包sub_package下 用uniapp的vue.config.js自定义…

【报名】2023产业区块链生态日暨 FISCO BCOS 开源六周年生态大会

作为2023深圳国际金融科技节系列活动之一,由深圳市地方金融监督管理局指导,微众银行、金链盟主办的“2023产业区块链生态日暨FISCO BCOS开源六周年生态大会”将于12月15日下午14:00在深圳举办。 今年的盛会将进一步升级,以“FISCO BCOS和TA的…

C/C++,图算法——求强联通的Tarjan算法之源程序

1 文本格式 #include <bits/stdc.h> using namespace std; const int maxn 1e4 5; const int maxk 5005; int n, k; int id[maxn][5]; char s[maxn][5][5], ans[maxk]; bool vis[maxn]; struct Edge { int v, nxt; } e[maxn * 100]; int head[maxn], tot 1; vo…

Nacos多数据源插件

Nacos从2.2.0版本开始,可通过SPI机制注入多数据源实现插件,并在引入对应数据源实现后,便可在Nacos启动时通过读取application.properties配置文件中spring.datasource.platform配置项选择加载对应多数据源插件.本文档详细介绍一个多数据源插件如何实现以及如何使其生效。 注意:…

动态规划 | 139. 单词拆分、多重背包

139、单词拆分 dp[i]&#xff1a;长度为 i 的字符串可以有字典中出现的单词拼接出来。 if s[j: i] in wordDict and dp[j] true 则 dp[i] true dp[0] true, 因为后续均由dp[0]推出。 从前向后遍历 public static boolean wordBreak(String s, List<String> wordDi…

简单取证-MISC-bugku-解题步骤

——CTF解题专栏—— 题目信息&#xff1a; 题目&#xff1a;简单取证 作者&#xff1a;Tokeii 提示&#xff1a;flag格式为flag{用户名_对应的密码} 例如flag{administrator_bugku} 解题附件&#xff1a; 解题思路&#xff1a; 取证自己属实不太擅长&#xff0c;所以找个题…

JMX的使用

1. 定义和意义 JMX是Java Management Extention的缩写&#xff0c;出发点是让外部通过属性/方法来读取或设置程序状态。对于提供对外服务的程序来说&#xff0c;天生就有这样的能力&#xff0c;Web程序通过HTTP接口对外暴露&#xff0c;RPC应用通过RPC接口暴露。不过带来的问…

如何快速选出一支好股票?

俗话说得好&#xff1a;股票选得好&#xff0c;收益少不了&#xff01;不用多说&#xff0c;相信大伙儿都知道选一支好股票究竟有多重要。 但是选股可不像咱们去菜市场买菜一样&#xff0c;看着顺眼就成。选股&#xff0c;其实是一个专业性特别强的技术活儿。 目前最常用的选股…

微信开发者工具真机调试连接状态在正常和未连接之间反复横跳

开启局域网模式能解决这个问题&#xff0c;目前只找到这一个方法

详解Linux常用命令

目录 1. ps 命令 2. top 命令 3. grep 命令 4. df 命令 5. tail 命令 6. head 命令 7. cat 命令 8. --help 和 man 命令 9. cd 命令 10. mkdir 命令 11. rm 命令 12. mv 和 cp 命令 13. touch 命令 14. vi 或 vim 命令 15. chmod 修改权限 16. 打包和压缩文件 …

电子学会C/C++编程等级考试2021年12月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:移动路线 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把…

Windows的常用cmd命令总结

文章目录 一.盘符切换二: cd命令(打开文件/文件夹)三:查看目录四.创建和删除文件夹五.查看本机ip地址六.清除当前屏幕七.复制文件到另一个地方八.移动文件到另一个地方九.删除文件&#xff08;不能删除文件夹&#xff09;十.测试网络连接十一.停止任务进程Windows快捷键总结大全…

python简单进阶之web框架:fastapi使用教程

原文&#xff1a;python简单进阶之web框架&#xff1a;fastapi使用教程 - 知乎 这是简单进阶教程系列第四篇&#xff0c;本系列文章主要介绍那些可以很快上手的进阶库。 我其实学过一段时间Django框架&#xff0c;但是半途而废了&#xff0c;我觉得可能还是简单一点的框架比较适…