Linux 系统是如何收发⽹络包的

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

⽹络模型

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

  • OSI模型分析

OSI(Open Systems Interconnection)模型是一个理论上的网络通信模型,由国际标准化组织(ISO)提出,目的是促进不同系统之间的通信标准化。它将网络通信分成了七个层次:

  1. 物理层(Physical Layer):负责通过物理媒体传输原始比特流。这涉及到数据接口、传输媒介(如电缆、光纤)和信号。
  2. 数据链路层(Data Link Layer):在物理层提供的服务上增加了数据帧的封装、物理地址寻址、流量控制等功能。
  3. 网络层(Network Layer):负责数据包的路由选择、传输和分片,以确保数据可以跨越不同的网络。
  4. 传输层(Transport Layer):提供端到端的通信服务,包括数据的分段、传输控制(如TCP的可靠传输)和错误检测。
  5. 会话层(Session Layer):管理应用程序之间的会话,包括会话的建立、维持和终止。
  6. 表示层(Presentation Layer):确保信息的语义以及它的格式在不同系统间能正确交换,例如加密、压缩和数据格式转换。
  7. 应用层(Application Layer):为最终用户提供网络服务接口,如HTTP、FTP和电子邮件服务。

OSI模型的优点在于它提供了一个清晰的网络通信分层框架,有助于不同网络技术和协议的开发和标准化。但在实践中,由于其复杂性和理论性,它并没有被广泛直接实现。

  • TCP/IP模型分析

TCP/IP模型是一种更实际、基于实际网络协议栈的网络通信模型,它简化了OSI模型的七层为四层:

  1. 应用层(Application Layer):相当于OSI模型的应用层、表示层和会话层,提供各种网络服务给终端用户,如HTTP、FTP、DNS等。
  2. 传输层(Transport Layer):与OSI模型的传输层类似,主要用于提供端到端的通信控制,主要协议有TCP(提供可靠的字节流服务)和UDP(提供无连接的数据报服务)。
  3. 网络层(Network Layer):负责数据包的路由选择和传输,主要协议是IP(Internet Protocol)。
  4. 网络接口层(Network Interface Layer):相当于OSI模型的物理层和数据链路层,负责数据的物理传输。

TCP/IP模型由于其简化的层次结构和实用性,成为了互联网的基础协议栈,得到了广泛的应用和发展。

image-20240321092147864

不过,我们常说的七层和四层负载均衡,是⽤ OSI ⽹络模型来描述的,七层对应的是应⽤
层,四层对应的是传输层。

  • 四层负载均衡适合对速度和低延迟有高要求的场景,但它无法进行复杂的决策。
  • 七层负载均衡适用于需要根据具体应用逻辑进行智能路由的场景,尽管它可能比四层负载均衡处理速度慢一些。

Linux ⽹络协议栈

我们可以把⾃⼰的身体⽐作应⽤层中的数据,打底⾐服⽐作传输层中的 TCP 头,外套⽐作⽹络层中 IP 头,帽⼦和鞋⼦分别⽐作⽹络接⼝层的帧头和帧尾。

在冬天这个季节,当我们要从家⾥出去玩的时候,⾃然要先穿个打底⾐服,再套上保暖外套,最后穿上帽⼦和鞋⼦才出⻔,这个过程就好像我们把 TCP 协议通信的⽹络包发出去的时候,会把应⽤层的数据按照⽹络协议栈层层封装和处理。
你从下⾯这张图可以看到,应⽤层数据在每⼀层的封装格式。

image-20240321092643945
  • 数据包的封装过程
  1. 应用层到传输层:当数据从应用层发送时,传输层(如TCP或UDP)会给数据包添加一个头部,这个头部包括端口号(用于标识发送和接收应用程序)、序列号(仅TCP,用于确保数据的有序和完整性)、确认号(仅TCP,用于确认接收)、以及其他控制信息(如窗口大小、校验和等)。
  2. 传输层到网络层:网络层(通常是IP层)再给这个已经有了传输层头部的数据包添加它自己的头部,这个IP头部包括源IP地址和目的IP地址(用于在网络中路由数据包),以及其他控制信息如生存时间(TTL)、协议类型等。
  3. 网络层到网络接口层:最后,在网络接口层(数据链路层和物理层的组合),数据包被进一步封装,加上了帧头和帧尾,这包括物理地址信息(MAC地址)、错误检测和校正码等。这个过程准备数据包在物理媒介上的传输,如以太网或Wi-Fi。
  • 最大传输单元(MTU)和分片

MTU是网络层面上可以传输的最大数据包大小。对于以太网,标准MTU大小通常是1500字节。如果一个IP数据包的大小超过了网络路径上的MTU,那么这个数据包就需要在网络层进行分片,以确保每个片段都不会超过MTU大小。分片的过程增加了额外的头部信息(因为每个片段都需要被独立地封装为有效的IP数据包),并且可能导致接收端需要重组这些片段,这一切都会引入额外的处理延迟。

  • 对网络性能的影响
  1. 增加开销:每层添加的头部信息增加了总的传输数据量。尽管这些协议头是必要的,它们占用了传输中的带宽,特别是当传输的有效负载较小时,这种开销比例会变得更大。
  2. 分片的处理:当数据包需要分片时,这不仅增加了传输的总字节数(因为每个片段都有自己的IP头部),还可能在接收端造成额外的重组开销。此外,如果任何一个片段在传输过程中丢失,整个数据包可能都需要重新发送,从而降低了网络的效率。
  3. 网络吞吐能力:理论上,较大的MTU可以提高网络的吞吐能力,因为它减少了因为分片所必需的开销和处理时间。然而,在实际环境中,最优的MTU大小还要考虑网络的特定条件,如链路类型、存在的干扰、以及网络拥塞情况。

知道了 TCP/IP ⽹络模型,以及⽹络包的封装原理后,Linux网络协议栈是一个实现了TCP/IP四层模型的复杂系统,负责处理从应用程序到物理网络媒介的所有数据传输。在Linux中,这个过程涉及多个组件和层次,每一层都有其特定的功能和责任。下面是对Linux网络协议栈的一般分析:

应用层与Socket层的交互

  • 应用程序与Socket层:应用程序通过系统调用与Socket层进行交互。Socket API提供了一组函数,允许应用程序创建套接字(socket),这些套接字用于发送和接收数据。在应用层,开发人员不需要关心数据是如何在网络中传输的;他们只需要使用标准的Socket接口,比如send()recv()函数,以及更高级的API,如HTTP库或数据库连接库,这些库在内部使用Socket进行通信。

Linux网络协议栈的核心层

  • 传输层:位于Socket层之下,主要处理端到端的数据传输,包括TCP和UDP协议的实现。TCP负责提供可靠的、有序的和基于字节流的连接,而UDP提供了一个简单的、不可靠的消息传递服务。
  • 网络层:负责数据包的路由和寻址。在这一层,IP协议是核心,它负责将数据包从源主机传输到目的主机,无论它们在网络中的位置如何。IP层也处理数据包分片和重组,以及错误报告(通过ICMP)。
  • 网络接口层:这一层包括数据链路层和物理层的功能,负责数据包的实际传输。在Linux中,这通常意味着与网络设备驱动程序的交互,网络设备驱动程序负责将数据包发送到物理媒体(例如,以太网)上,以及从物理媒体接收数据包。

网卡驱动程序和硬件网卡设备

  • 网卡驱动程序和硬件网卡:这是Linux网络协议栈的最底层。网卡驱动程序负责与硬件网卡设备通信,执行如初始化设备、处理中断、发送和接收数据包等操作。硬件网卡是物理设备,负责电信号的发送和接收。
image-20240321093418655

Linux 接收⽹络包的流程

Linux系统接收网络包的流程是一个精心设计的机制,旨在有效管理网络流量和CPU资源。这个流程利用了硬件(网卡)和软件(操作系统内核)之间的协作,确保在高性能网络环境下,系统能够高效地处理大量网络数据包,而不会过度占用CPU资源。以下是对该流程的详细分析:

  • 网络包的接收
  1. 网卡接收网络包:当网卡接收到一个网络包时,它使用直接内存访问(DMA)技术,将网络包直接写入到预先分配的内存区域,通常是一个环形缓冲区(Ring Buffer)。这个过程不需要CPU的直接干预,提高了数据传输的效率。
  2. 中断触发:接收到网络包后,网卡会触发一个硬件中断,通知CPU有新的数据到达。在传统的处理机制中,每接收一个网络包就会触发一次中断,这在网络流量较低时是可行的,但在高流量环境下会导致大量的中断,严重影响系统性能。
  • NAPI(New API)机制

为了解决上述问题,Linux内核引入了NAPI机制,它是一种混合使用中断和轮询的方法来处理网络数据包的接收。NAPI的工作流程如下:

  1. 初次中断:当第一个网络包到达并通过DMA写入内存后,网卡会触发一个硬件中断。
  2. 中断处理函数:CPU响应硬件中断,并执行注册的中断处理函数。这个函数的首要任务是暂时禁用进一步的中断。这意味着,在这个阶段,即使有新的网络包到达,也不会触发新的硬件中断。
  3. 启用软中断:中断处理函数随后会触发一个软中断(或者称为“下半部”处理),并重新启用硬件中断。软中断负责实际的数据包处理工作,如从环形缓冲区中读取数据包并进行进一步处理。
  4. 轮询模式:在软中断处理期间,系统进入轮询模式,这时系统会主动检查环形缓冲区中是否有新的数据包到达,而不是依赖硬件中断。这种方式显著减少了中断的次数,降低了CPU的负载。
  5. 恢复中断模式:当环形缓冲区中没有更多的数据包需要处理时,系统会退出轮询模式,并恢复到正常的中断驱动模式。这样,下一个到达的网络包会再次触发硬件中断,重启整个流程。
  • 效率提升

通过NAPI机制,Linux能够在保持高吞吐量的同时,显著减少CPU的中断负载。在高性能网络环境中,这种机制可以有效地平衡网络包处理速度和系统资源使用,提高了系统的整体性能和稳定性。NAPI通过减少在高流量情况下不必要的中断,使CPU可以更好地执行其他任务,从而优化了多任务处理环境下的资源分配。

ksoftirqd线程处理软中断

  • ksoftirqd线程:Linux内核中的ksoftirqd线程负责处理软中断。每个CPU都有一个对应的ksoftirqd线程。当网络流量较高时,软中断处理会从硬件中断上下文转移到这些线程中,以减少硬件中断处理对系统性能的影响。
  • 数据处理ksoftirqd线程会轮询处理环形缓冲区(Ring Buffer)中的数据。这些数据以数据帧的形式存储,通常使用sk_buff(socket buffer)结构来表示,它是一个关键的数据结构,用于在Linux网络栈中传递网络包。

网络协议栈处理

  1. 网络接口层:处理开始于网络接口层,这里会进行报文的基本检查(如合法性检查)。对于合法的报文,根据帧头信息确定上层协议类型(例如IPv4或IPv6),然后移除帧头和帧尾,将剩余内容传递到网络层。
  2. 网络层:在网络层,IP包被进一步处理。这一层负责判断网络包的目的地,是直接上交给上层处理(如TCP或UDP处理)还是需要路由转发。
  3. 传输层:到达传输层时,会根据IP头中指定的协议(TCP或UDP)去掉IP头,再根据包头信息(如TCP头或UDP头)处理数据。此层利用源IP、源端口、目标IP和目标端口这四元组唯一标识找到对应的Socket,并将数据放入Socket的接收缓冲区。
  4. 应用层:应用层程序通过调用Socket API,如recv(),将数据从内核的Socket接收缓冲区拷贝到应用层的缓冲区,并处理数据。完成这一步骤后,数据包的接收过程就结束了。

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

image-20240321094613791

Linux 发送⽹络包的流程

Linux发送网络包的过程是一个从应用层数据到物理传输的完整路径,涉及数据在协议栈各层的处理和转换。这个过程确保了数据按照TCP/IP模型的要求被正确封装、路由、发送,最后通过物理网络到达目标。下面是对这个过程的分析:

1. 应用层到内核态的数据传输

  • Socket发送数据包接口:应用程序通过调用Socket API(如sendwrite函数)发起数据传输请求。这个操作会使得进程从用户态陷入到内核态。

  • sk_buff结构体:内核为了处理这些待发送的数据,会申请一个sk_buff(socket buffer)结构体的内存空间,这个结构是Linux网络子系统中一个关键的数据结构,用于在内核中表示网络数据包。应用层的数据会被拷贝到这个sk_buff中,并加入到发送缓冲区。

2. 网络协议栈处理

  • TCP/IP协议栈处理:从Socket发送缓冲区中取出sk_buff后,数据包会按照TCP/IP协议栈从上到下逐层进行处理。

  • TCP传输与sk_buff副本:如果是TCP传输,因为TCP支持数据的丢失重传,所以会创建一个sk_buff的副本。原始sk_buff用于实际发送,而副本在收到对方的ACK确认前,用于可能的重传。

3. 数据包的封装

  • 填充协议头:在向下传递的过程中,每一层都会向sk_buff中添加相应的协议头(如TCP头、IP头和以太网帧头)。这⾥提⼀下,sk_buff 可以表示各个层的数据包,在应⽤层数据包叫 data,在 TCP 层我们称为 segment,在 IP 层我们叫 packet,在数据链路层称为frame。

  • sk_buff指针调整:通过调整sk_buff中的data指针的方法,避免了在层与层之间传递数据时发生的多次拷贝,提高了CPU效率。

    当接收报⽂时,从⽹卡驱动开始,通过协议栈层层往上传送数据报,通过增加 skb->data
    的值,来逐步剥离协议⾸部。
    当要发送报⽂时,创建 sk_buff 结构体,数据缓存区的头部预留⾜够的空间,⽤来填充各
    层⾸部,在经过各下层协议时,通过减少 skb->data 的值来增加协议⾸部。

    image-20240321095652054

4. 数据发送准备

  • 网络层处理:在网络层,会进行路由选择(确认下⼀跳的 IP)、IP头填充、netfilter过滤、对大于MTU的数据包进行分片等处理。

  • 网络接口层处理:在这一层,会通过ARP协议确定下一跳的MAC地址,并填充帧头帧尾,将sk_buff放入网卡的发送队列。

5. 数据包的物理发送

  • 触发软中断:软中断被触发来通知网卡驱动程序有新的网络包待发送。

  • 网卡驱动处理:网卡驱动从发送队列中读取sk_buff,将数据映射到网卡的DMA区域,并触发物理发送。

6. 发送完成与内存清理

  • 发送完成中断:数据发送完成后,网卡设备会触发一个硬件中断来通知CPU,主要任务是释放sk_buff内存和清理环形缓冲区。

  • 确认ACK与释放资源:对于TCP传输,一旦收到对方的ACK确认,传输层就会释放掉原始的sk_buff副本。

这个过程展现了Linux内核如何高效、有序地处理网络数据包的发送,从应用层数据的准备到最终的物理传输,每一步都经过精心设计,确保数据的正确传输和系统资源的有效利用。

发送⽹络数据的时候,涉及⼏次内存拷⻉操作?

    1. 从用户空间到内核空间的拷贝

当应用程序调用发送数据的系统调用(如sendwrite)时,数据需要从用户空间传输到内核空间。此时,内核会为这些待发送的数据申请一个sk_buff结构体的内存,并将用户空间的数据拷贝到这个sk_buff内存中。这个sk_buff随后被加入到发送缓冲区。这是第一次内存拷贝操作。

    1. TCP协议的sk_buff克隆

对于使用TCP传输协议的情况,为了实现TCP的可靠传输(即支持数据的重传机制),在从传输层向网络层转发数据时,会克隆一个新的sk_buff副本。这个副本是实际被发送到网络层的,而原始的sk_buff保留在传输层,用于在需要时重新发送数据(如未收到对方的ACK确认)。这个副本在发送完成后会被释放,而原始的sk_buff在收到对方的ACK确认后才会被释放。这是第二次内存拷贝操作。

    1. 处理大于MTU的sk_buff

当网络层发现一个sk_buff的大小超过了MTU(最大传输单元)时,会进行分片处理。这意味着原始的sk_buff会被分割成多个小的sk_buff,每个都小于或等于MTU的大小。为了分片,内核会为每个片段申请新的sk_buff内存,并将原始sk_buff的相应部分数据拷贝到这些新的sk_buff中。这是第三次内存拷贝操作。

因此,在发送网络数据的过程中,涉及到的内存拷贝操作主要有三次:一次是从用户空间到内核空间的拷贝,第二次是TCP协议的sk_buff克隆操作,第三次是处理超过MTU大小需要分片的情况。需要注意的是,第三次拷贝操作只在原始sk_buff大于MTU时才会发生。这些内存拷贝操作确保了数据的正确处理和传输,同时支持了TCP的可靠传输机制。

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

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

相关文章

亚马逊云科技:企业如何开启生成式AI之旅?

如果要评选最近两年全球科技行业最热门的细分领域,那么生成式AI绝对会以遥遥领先的票数成为当仁不让的冠军。 然而眼见生成式AI发展得如火如荼,越来越多的企业却陷入了深深的焦虑:应该如何开启生成式AI之旅?又该怎样搭建大模型&am…

对七层代理、四层代理、正向代理、反向代理的认识

一、理解nginx服务代理 Nginx代理有正向和反向代理两种类型,可以基于osi七层模型中的第四层(传输层)和第七层(应用层)进行代理 注: nginx 一般支持的是7层代理,支持四层代理一般使用 lvs 或者ha…

Data.olllo:一键去除相同内容数据列!

引言: 在数据处理的舞台上,重复数据常常像调皮的小精灵一样,频繁出现,让人头疼不已。但现在,有了Data.olllo的神奇功能,您可以一键去除相同内容数据列,让数据处理变得轻松愉快! 功能…

虹科Pico汽车示波器 | 免拆诊断案例 | 2019 款东风悦达起亚K2车怠速起停系统工作异常

一、故障现象 一辆2019款东风悦达起亚K2车,搭载G4FG发动机,累计行驶里程约为9 400 km。车主反映,行驶至路口停车等红灯时,怠速起停(ISG)系统自动使发动机熄火,接着组合仪表提示“怠速起停已解除…

某东联盟js逆向

声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!wx a15018601872 本文章…

mysql无法看到3306端口监听

参考:https://blog.csdn.net/shumeigang/article/details/103902459 mysql> show global variables like ‘port’; 是0 原因是我的my.cnf有话: skip-network 或 注释掉,然后重新启动下数据库,运行netstat -an|grep 3306 就可以看到了

C#非强签名dll搜索顺序

由于不是强签名dll,所以无效考虑全局程序集缓存 (GAC)。 预备工作 新建解决方案ClassLibrary1,新建类库ClassLibrary1,新建控制台程序ShowDllLoc。 利用VS添加引用。 一,利用app.config设置codebase,设置dll的加载路径为:code…

C#探索之路基础篇(1):编程中面向过程、数据、对象的概念辨析

文章目录 C#探索之路基础篇(1):编程中面向过程、数据、对象的概念辨析1 面向过程编程1.1 概念1.2 示例代码:1.3 使用范围与时机:1.4 注意事项:1.5 通俗讲法 2 面向对象编程2.1 概念2.2 示例代码2.3 使用范围2.4 注意事项2.5 通俗讲…

软考高级:UML定时图概念和例题

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

KW音乐搜索参数

声明: 本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标: …

【Git】第一课:Git的介绍

简介 什么是Git? Git是一个开源的分布式版本控制系统,用于跟踪代码的改变和协同开发。它最初由Linus Torvalds为了管理Linux内核开发而创建,现已成为开源软件开发中最流行的版本控制系统,没有之一。Git允许多人同时在不同的分支上工作&…

【leetcode热题】轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4…

Linux配置bond(网卡绑定)

Linux配置bond(网卡绑定) 最近需要搭建测试环境,为了保证带宽不成为瓶颈,就需要使用bond来提升网络带宽 1 概念、原理、工作模式 1.1 概念:网卡捆绑 网卡绑定,也称作网卡捆绑。就是将两个或者更多的物理网卡绑定成一…

Leetcode 200. 岛屿数量

心路历程: 在没有看图论这一章之前看这道题没什么直接的思路,在看完图论之后,学着使用DFS和BFS去套用解决。第一次自己做的时候还是遇到了很多小问题。整体思路很流畅,但是需要处理的细节第一次没怎么处理好,花了很多…

Postgresql数据库入门简介

Postgresql入门 1.Postgresql数据库简介 PostgresQL是一个功能强大的开源数据库系统。经过长达15年以上的积极开发和不断改进,PostgreSQL已在可靠性、稳定性、数据一致性等获得了业内极高的声誉。目前PostgreSql可以运行在所有主流操作系统上,包括Linux…

WebGIS管线在线编辑器(电力、水力、燃气、热力、热能管线)

随着GIS等信息技术的发展,地下管线管理也从二维平面向三维立体管理迈进。传统管线信息管理系统将管线及其附属设施抽象成二维平面内的点、要素,并使用各类点符号、不同颜色线段进行表达。虽能一定程度上满足城市智慧运行的需要,但不能很直观的…

分布式锁简单实现

分布式锁 Redis分布式锁最简单的实现 想要实现分布式锁,必须要求 Redis 有「互斥」的能力,我们可以使用 SETNX 命令,这个命令表示SET if Not Exists,即如果 key 不存在,才会设置它的值,否则什么也不做。 …

Premiere模板|200个视频标题文字动画pr字幕模板包

Premiere模板,13个类别200个Pr视频标题字幕文字动画模板mogrt包。 几乎适用于任何场景。粗体标题,标注,未来主义和线条标题,下三分之一,霓虹灯,带数字的标题,倒计时,表格&#xff0c…

【Mock|JS】Mock的get传参+获取参数信息

mockjs的get传参 前端请求 const { data } await axios("/video/childcomments", {params: {sort: 1,start: 2,count: 5,childCount: 6,commenIndex: 0,},});后端获取参数 使用正则匹配url /*** # 根据url获取query参数* param {Url} urlStr get请求获取参数 eg:…

回归预测 | Matlab基于SAO-BiLSTM雪融算法优化双向长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SAO-BiLSTM雪融算法优化双向长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SAO-BiLSTM雪融算法优化双向长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SAO-B…