【Linux是如何发送网络包的?】

news2025/1/19 19:27:26

网络模型

为了使得多种设备能通过网络相互通信,和为了解决各种不同设备在网络互联中的兼容性问题,国际标准化组织制定了开放式系统互联通信参考模型(Open System Interconnection Reference Model),也就是 OSI 网络模型,该模型主要有 7 层,分别是应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层。

每一层负责的职能都不同,如下:

应用层,负责给应用程序提供统一的接口;
表示层,负责把数据转换成兼容另一个系统能识别的格式;
会话层,负责建立、管理和终止表示层实体之间的通信会话;
传输层,负责端到端的数据传输;
网络层,负责数据的路由、转发、分片;
数据链路层,负责数据的封帧和差错检测,以及 MAC 寻址;
物理层,负责在物理网络中传输数据帧;
由于 OSI 模型实在太复杂,提出的也只是概念理论上的分层,并没有提供具体的实现方案。

事实上,我们比较常见,也比较实用的是四层模型,即 TCP/IP 网络模型,Linux 系统正是按照这套网络模型来实现网络协议栈的。

TCP/IP 网络模型共有 4 层,分别是应用层、传输层、网络层和网络接口层,每一层负责的职能如下:

应用层,负责向用户提供一组应用程序,比如 HTTP、DNS、FTP 等;
传输层,负责端到端的通信,比如 TCP、UDP 等;
网络层,负责网络包的封装、分片、路由、转发,比如 IP、ICMP 等;
网络接口层,负责网络包在物理网络中的传输,比如网络包的封帧、 MAC 寻址、差错检测,以及通过网卡传输网络帧等;
TCP/IP 网络模型相比 OSI 网络模型简化了不少,也更加易记,它们之间的关系如下图
在这里插入图片描述
不过,我们常说的七层和四层负载均衡,是用 OSI 网络模型来描述的,七层对应的是应用层,四层对应的是传输层。

Linux 网络协议栈

我们可以把自己的身体比作应用层中的数据,打底衣服比作传输层中的 TCP 头,外套比作网络层中 IP 头,帽子和鞋子分别比作网络接口层的帧头和帧尾。

在冬天这个季节,当我们要从家里出去玩的时候,自然要先穿个打底衣服,再套上保暖外套,最后穿上帽子和鞋子才出门,这个过程就好像我们把 TCP 协议通信的网络包发出去的时候,会把应用层的数据按照网络协议栈层层封装和处理。

你从下面这张图可以看到,应用层数据在每一层的封装格式。

在这里插入图片描述
其中:

传输层,给应用数据前面增加了 TCP 头;
网络层,给 TCP 数据包前面增加了 IP 头;
网络接口层,给 IP 数据包前后分别增加了帧头和帧尾;
这些新增的头部和尾部,都有各自的作用,也都是按照特定的协议格式填充,这每一层都增加了各自的协议头,那自然网络包的大小就增大了,但物理链路并不能传输任意大小的数据包,所以在以太网中,规定了最大传输单元(MTU)是 1500 字节,也就是规定了单次传输的最大 IP 包大小。

当网络包超过 MTU 的大小,就会在网络层分片,以确保分片后的 IP 包不会超过 MTU 大小,如果 MTU 越小,需要的分包就越多,那么网络吞吐能力就越差,相反的,如果 MTU 越大,需要的分包就越少,那么网络吞吐能力就越好。

知道了 TCP/IP 网络模型,以及网络包的封装原理后,那么 Linux 网络协议栈的样子,你想必猜到了大概,它其实就类似于 TCP/IP 的四层结构:
在这里插入图片描述
从上图的的网络协议栈,你可以看到:

应用程序需要通过系统调用,来跟 Socket 层进行数据交互;
Socket 层的下面就是传输层、网络层和网络接口层;
最下面的一层,则是网卡驱动程序和硬件网卡设备;

Linux 接收网络包的流程

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

那应该怎么告诉操作系统这个网络包已经到达了呢?
最简单的一种方式就是触发中断,也就是每当网卡收到一个网络包,就触发一个中断告诉操作系统。

但是,这存在一个问题,在高性能网络场景下,网络包的数量会非常多,那么就会触发非常多的中断,要知道当 CPU 收到了中断,就会停下手里的事情,而去处理这些网络包,处理完毕后,才会回去继续其他事情,那么频繁地触发中断,则会导致 CPU 一直没完没了的处理中断,而导致其他任务可能无法继续前进,从而影响系统的整体效率。

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

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

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

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

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

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

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

网络协议栈

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

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

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

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

至此,一个网络包的接收过程就已经结束了,你也可以从下图左边部分看到网络包接收的流程,右边部分刚好反过来,它是网络包发送的流程。

在这里插入图片描述

Linux 发送网络包的流程

如上图的右半部分,发送网络包的流程正好和接收流程相反。

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

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

如果使用的是 TCP 传输协议发送数据,那么先拷贝一个新的 sk_buff 副本 ,这是因为 sk_buff 后续在调用网络层,最后到达网卡发送完成的时候,这个 sk_buff 会被释放掉。而 TCP 协议是支持丢失重传的,在收到对方的 ACK 之前,这个 sk_buff 不能被删除。所以内核的做法就是每次调用网卡发送的时候,实际上传递出去的是 sk_buff 的一个拷贝,等收到 ACK 再真正删除。

接着,对 sk_buff 填充 TCP 头。这里提一下,sk_buff 可以表示各个层的数据包,在应用层数据包叫 data,在 TCP 层我们称为 segment,在 IP 层我们叫 packet,在数据链路层称为 frame。

你可能会好奇,为什么全部数据包只用一个结构体来描述呢?协议栈采用的是分层结构,上层向下层传递数据时需要增加包头,下层向上层数据时又需要去掉包头,如果每一层都用一个结构体,那在层之间传递数据的时候,就要发生多次拷贝,这将大大降低 CPU 效率。

于是,为了在层级之间传递数据时,不发生拷贝,只用 sk_buff 一个结构体来描述所有的网络包,那它是如何做到的呢?是通过调整 sk_buff 中 data 的指针,比如:

当接收报文时,从网卡驱动开始,通过协议栈层层往上传送数据报,通过增加 skb->data 的值,来逐步剥离协议首部。
当要发送报文时,创建 sk_buff 结构体,数据缓存区的头部预留足够的空间,用来填充各层首部,在经过各下层协议时,通过减少 skb->data 的值来增加协议首部。
你可以从下面这张图看到,当发送报文时,data 指针的移动过程。
在这里插入图片描述
至此,传输层的工作也就都完成了。

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

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

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

当数据发送完成以后,其实工作并没有结束,因为内存还没有清理。当发送完成的时候,网卡设备会触发一个硬中断来释放内存,主要是释放 sk_buff 内存和清理 RingBuffer 内存。

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

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

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

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

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

总结

电脑与电脑之间通常都是通过网卡、交换机、路由器等网络设备连接到一起,那由于网络设备的异构性,国际标准化组织定义了一个七层的 OSI 网络模型,但是这个模型由于比较复杂,实际应用中并没有采用,而是采用了更为简化的 TCP/IP 模型,Linux 网络协议栈就是按照了该模型来实现的。

TCP/IP 模型主要分为应用层、传输层、网络层、网络接口层四层,每一层负责的职责都不同,这也是 Linux 网络协议栈主要构成部分。

当应用程序通过 Socket 接口发送数据包,数据包会被网络协议栈从上到下进行逐层处理后,才会被送到网卡队列中,随后由网卡将网络包发送出去。

而在接收网络包时,同样也要先经过网络协议栈从下到上的逐层处理,最后才会被送到应用程序。

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

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

相关文章

【工作中掌握10个就够了!!!】Linux中的10个最常见命令+vim三个基本操作

欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)   文章字体风格: 红色文字表示:重难点★✔ 蓝色文字表示&#…

【macOS自带VNC远程】——Windows在外远程桌面控制macOS

文章目录 前言1.测试局域网内远程控制1.1 macOS打开屏幕共享1.2 测试局域网内VNC远程控制 2. 测试公网远程控制2.1 macOS安装配置cpolar内网穿透2.2 创建tcp隧道,指向5900端口 3. 测试公网远程控制4. 配置公网固定TCP地址4.1 保留固定TCP地址4.2 配置固定TCP端口地址…

Java | 一分钟掌握定时任务 | 4 - 多线程的Timer

作者:Mars酱 声明:本文章由Mars酱原创,部分内容来源于网络,如有疑问请联系本人。 转载:欢迎转载,转载前先请联系我! 前言 JDK自带的Timer是无法做到多任务并发的,那么我们怎么处理多…

如何编写一份优质软件测试工程师简历的范文【建议收臧】

很多刚转行软件测试的小伙伴是不是不知道怎么写好一份优质的软件测试工程师的简历。今天呢,就给大家分享一下一个优质软件测试工程师简历的范文。记得收藏起来哦。 下面的案例:2-3年的软件测试工程的简历 姓 名:XXX 学历&#xff1a…

Zabbix“专家坐诊”第191期问答汇总

问题一 Q:snmp监控服务器风扇、温度等硬件信息需要要mib库吗? A:官网有相关的mib库可查,一般同大型号通用,直接去官方下就行。 问题二 Q:zabbix用的postgresqltimescaledb备份这个数据库的时候不想包含历…

【Linux】-Linux的权限

💖作者:小树苗渴望变成参天大树 ❤️‍🩹作者宣言:认真写好每一篇博客 💨作者gitee:gitee 💞作者专栏:C语言,数据结构初阶,Linux,C 如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 …

【C++】入门必备小知识

C入门 1. 域2. 命名空间2.1命名空间的定义2.2 命名空间的使用 3. C输入和输出4. 缺省参数5. 函数重载6. 引用7. auto8. 范围for9.nullptr空指针10.内联函数 1. 域 域就是作用域,同一个域不可以用同名的变量,不同域可以用同名变量,遵循局部优…

案例11:Java超市管理系统设计与实现开题报告

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

5年时间里,自动化测试于我带来的意义,希望你也能早点知道

摘要:在我有限的软件测试经历里,曾有一段专职的自动化测试经历。 接触自动化 那时第一次上手自动化测试,团队里用的是Python,接口自动化测试的框架是requestsExcelJenkins,APP自动化测试的框架是Appium。 整个公司当…

寻找差值结构的最优顺序

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点,AB训练集各由6张二值化的图片组成,让A中有6个1 差值结构的每行只能是二进制的3,6,5..3列每列1的数量为1,2,3.B中全是0,排列组合…

“记录新时代 奋进新征程”省市主流媒体共赴省交通集团在建项目采风

近日,浙江省省市13家主流媒体集中走进杭绍甬高速杭绍段绍兴侧路面施工现场、杭金衢高速联络线PPP项目中村大桥及杨家山隧道等施工现场,近距离感受在建工程的标准化施工、数字化赋能以及产业工人队伍打造。 标准化、数字化齐头并进,保障路面施…

脂溶性荧光染料Cy7标记羧酸Cy7-COOH/Carboxylic acids星戈瑞

CY7-COOH是一种含有羧基的化合物,它的分子式为C37H45ClN2O2,分子量519.12。其化学结构中包含有一个吲哚菁骨架,以及一个羧基(COOH)官能团。它的分子式为C37H45ClN2O2,分子量519.12。CY7-COOH是一种近红外荧…

热烈祝贺百华鞋业通过山东省专精特新企业认定!

近日,山东省工业和信息化厅公布了山东省2023年度专精特新中小企业名单,百华鞋业荣誉上榜! 专精特新中小企业是指具有“专业化、精细化、特色化、新颖化”特征的中小企业,多专注于产业链上某个环节,主营业务聚焦&#…

Three.js--》实现3d小岛模型搭建

目录 项目搭建 初始化three.js基础代码 设置环境背景 设置水面样式 添加天空小岛 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还…

AR和VR技术的进展和应用:如何为移动应用开发添加更多趣味和体验?

章节一:引言 作为一名移动应用开发者,我一直致力于为用户提供创新和令人兴奋的体验。随着技术的不断发展,AR和VR技术成为了实现这一目标的有力工具。无论是增强现实还是虚拟现实,它们都能够将虚拟世界与现实世界相结合&#xff0…

可移动磁盘“未格式化”提示?教程帮你重获数据!

可移动磁盘在使用的过程中会出现各种奇怪的错误,比如小编今天碰到的一个,打开分区提示未格式化!可移动磁盘“未格式化”提示?教程帮你重获数据! 可移动磁盘“未格式化”提示?教程帮你重获数据! …

【新星计划·2023】常用的5种VLAN的划分方式,你知道几种?

在说VLAN划分方式之前,先来说一说什么是VLAN?为什么需要划分VLAN? 一、什么是VLAN VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。每个VLAN是一个广播域,VLA…

我还是劝你别去外包,干了4年,废了.....

先说一下自己的情况,大专生,18年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

AVUE样式、刷新、字典、清空搜索条件等操作

1、操作栏、表格样式的控制 2、下拉框字典的设置 3、日期格式的设置 const dateFormat function(row, value) { if (!value) return ; let format YYYY-mm-dd; let date new Date(value); const dataItem { Y: date.getFullYear().toString(), m: (date.ge…

使用midjourney搞出一套三国人物画像!

当下已进入如火如荼的全民AI时代,最近体验了下midjourney,使用它的以图生图功能生成出来一套三国人物画像,和大家分享下使用心得。 使用midjourney的准备工作 下载工具 使用midjourney生产图片依赖的工具和流程,大致如下&#x…