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

news2024/9/20 5:52:47

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.coloradmin.cn/o/1536131.html

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

相关文章

了解Kafka位移自动提交的秘密:避免常见陷阱的方法

欢迎来到我的博客,代码的世界里,每一行都是一个故事 了解Kafka位移自动提交的秘密:避免常见陷阱的方法 前言位移自动提交简介自动提交的优缺点自动提交位移的优点:自动提交位移的缺点:自动提交与手动提交的对比分析&am…

安捷伦Agilent E4440A频谱分析仪

181/2461/8938产品概述: 这是一篇关于安捷伦Agilent E4440A频谱分析仪的详细指南。在这篇文章中,您将了解该设备的基本概述、技术规格、使用方法、应用场景以及与其他类似设备的比较。让我们一起深入了解Agilent E4440A频谱分析仪的各个方面。 让我们简…

软件杯 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习 机器视觉 人脸识别系统 该项目…

DashVector - 阿里云向量检索服务

DashVector 文章目录 DashVector一、关于 DashVector二、使用 DashVector 前提准备1、创建Cluster:2、获得API-KEY3、安装最新版SDK 三、快速使用 DashVector1. 创建Client2. 创建Collection3、插入Doc4、相似性检索5、删除Doc6. 查看Collection统计信息7. 删除Coll…

js中多重引号会导致函数的参数失效报错-Invalid or unexpected token

在js使用中我们经常会使动态添加html信息到元素对象中,且还加入了函数及其,函数对应参数,这个时候就会使用多重引号去拼接,如果拼接中没有做引号的转义,就会出现Invalid or unexpected token。 例如以下代码&#xff0…

【嵌入式——QT】Charts常见的图表的绘制

【嵌入式——QT】Charts常见的图表的绘制 柱状图QBarSetQBarSeriesQBarCategoryAxis图示 饼图堆叠柱状图百分比柱状图散点图和光滑曲线图代码示例 柱状图 QBarSet 用于创建柱状图的数据集。 主要函数 setLabel():设置数据集标签 ;setLabelBrush()&am…

复习斐波那契(用C++写)

或者这样写: 斐波那契数列 题目描述 斐波那契数列是指这样的数列:数列的第一个和第二个数都为 1 1 1,接下来每个数都等于前面 2 2 2 个数之和。 给出一个正整数 a a a,要求斐波那契数列中第 a a a 个数是多少。 输入格式…

Windows下MySQL服务启动常见的两种方式,完美适配Mysql5.7,MySql8.0

文章目录 一、图形界面下启动mysql服务二、在命令行重新启动mysql服务3 推荐阅读4 源码获取: Windows系统下,MySQL服务的启动,常见的两种启动方式如下: 一、图形界面下启动mysql服务 在图形界面下启动mysql服务的流程如下&#x…

算法体系-13 第十三 二叉树的基本算法+二叉树的递归套路

一 完全二叉树的判断 1.1 描述 完全二叉树:他每一层都是满的,即使不满也是最后一层不满,最后一层不满也是从左到右变满的;话句话说就是 完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充&#x…

Elasticsearch数据存储优化方案

优化Elasticsearch数据存储有助于提升系统性能、降低成本、提高数据查询效率以及增强系统的稳定性和可靠性。通常我们再优化Elasticsearch数据存储会遇到一些问题,导致项目卡壳。以下是优化Elasticsearch数据存储的一些重要作用: 1、问题背景 在某些场景…

我的春招求职面经

智能指针在面试时经常被问到,最近自己也在写,有一点思考,于是找到了这样一个题目,可以看看,上面这个代码有什么问题?留言区说出你的答案吧! 最后分享一下之前的实习->春招->秋招等文章汇总…

地质灾害在线监测,精准预警智能化

自然灾害无情且威力巨大,对人类生命财产安全造成严重威胁。地质灾害作为重要的自然灾害类型之一,给人类社会带来了沉重的经济损失和生命威胁。及时掌握地质灾害信息,提高预警能力和监测水平,是保障人民群众生命财产安全的当务之急。(key-iot.com.cn/18703.html&…

Juniper SRX 防火墙基础上网配置

简介 基于PNET-LAB模拟器,使用 vSRX-NG 23.4R1.9 镜像进行实验。 博客:https://songxwn.com/Juniper-SRX-snat/ 实验需求 配置WAN口 LAN口,实现基础的上网功能。配置NAT、DHCP。 ISP 路由器使用Cisco IOS模拟,与SRX对接口配置…

docker镜像安装空间不足no space left on device

报错:Error processing tar file(exit status 1): open /usr/local/lib/libmkl_tbb_thread.so.1: no space left on device 原先docker模型保存位置: docker info -f ‘{{ .DockerRootDir}}’ docker 高点版本,这里26.0 解决参考&#xf…

力扣---零钱兑换---动态规划

思路: 这是一道典型的动态规划问题(希望下次不用提示,能直接认出来):我将g[i]定义为总金币为i所需的最少硬币个数。所以递推公式可以表示为:g[i]min(g[i-1],g[i-2],g[i-5])1,也就是g[i]min(g[i-…

demo版多人聊天系统

目录 ​编辑 一,引入 二,在Server端修改的代码 1,保存用户信息功能实现 2,拼接消息 3,广播消息 三, Client端要修改的代码 四,效果演示 一,引入 在上一篇文章udp网络服务器中&a…

Java-Java基础学习(4)-多线程(2)

3.7. Lambda表达式 为什么要使用lambda表达式 避免匿名内部类定义过多;可以让代码看起来更简洁;去掉一堆没有意义的代码,只留下核心逻辑 属于函数式编程的概念,格式 (params) -> expression [表达式](params) -> statement…

山东省大数据局副局长禹金涛一行莅临聚合数据走访调研

3月19日,山东省大数据局党组成员、副局长禹金涛莅临聚合数据展开考察调研。山东省大数据局数据应用管理与安全处处长杨峰,副处长都海明参加调研,苏州市大数据局副局长汤晶陪同。聚合数据董事长左磊等人接待来访。 调研组一行参观了聚合数据展…

安装OneNote for Win10 | Win10/Win11

前言 PC端的OneNote分为2个版本,分别是Microsoft Store版本和Office版本,Microsoft Store版本即为OneNote for Win10,此版的OneNote有最近笔记功能,但检索功能不如Office版本,个人认为2个版本各有优劣。 但OneNote f…

详细剖析多线程(更新中...)

文章目录 前言一、认识线程1.1线程概念1.2为什么要有线程1.3线程和进程的区别(经典面试题) 二、创建线程2.1继承 Thread 类,重写run2.2实现 Runnable 接口,重写run2.3继承 Thread 类,重写run,匿名内部类2.4实现 Runnable 接口,重写run&#x…