计算机网络⑩ —— Linux系统如何收发网络包

  • 转载于小林coding:https://www.xiaolincoding.com/network/1_base/how_os_deal_network_package.html

1. OSI七层模型

  • 应用层,负责给应用程序提供统一的接口;
  • 表示层,负责把数据转换成兼容另一个系统能识别的格式;
  • 会话层,负责建立、管理和终止表示层实体之间的通信会话;
  • 传输层,负责端到端的数据传输;
  • 网络层,负责数据的路由、转发、分片;
  • 数据链路层,负责数据的封帧和差错检测,以及 MAC 寻址;
  • 物理层,负责在物理网络中传输数据帧;- 应用层,负责给应用程序提供统一的接口;

2. 数据传输过程

在这里插入图片描述

  • 传输层,给应用数据前面增加了 TCP 头;
  • 网络层,给 TCP 数据包前面增加了 IP 头;
  • 网络接口层,给 IP 数据包前后分别增加了帧头和帧尾;
  • 数据链路层中并不能传输任意大小的数据包,所以在以太网中,规定了最大传输单元(MTU)是 1500 字节,也就是规定了单次传输的最大 IP 包大小
    • 当网络包超过 MTU 的大小,就会在网络层分片,以确保分片后的 IP 包不会超过 MTU 大小
    • 如果 MTU 越小,需要的分包就越多,那么网络吞吐能力就越差
    • 如果 MTU 越大,需要的分包就越少,那么网络吞吐能力就越好

3. Linux 网络协议栈

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

在这里插入图片描述

4. Linux 接收网络包的流程

  • 网卡是计算机里的一个硬件,专门负责接收和发送网络包,当网卡接收到一个网络包后,会通过 DMA 技术,将网络包写入到指定的内存地址,也就是写入到 Ring Buffer ,这个是一个环形缓冲区,接着就会告诉操作系统这个网络包已经到达。
  • 告知操作系统网络包已到达的方式:
    • 触发中断:每当网卡收到一个网络包,就触发一个中断告诉操作系统
      • 问题:在高性能网络场景下,网络包的数量会非常多,那么就会触发非常多的中断,CPU收到中断后会先去处理这件事,因此会影响系统的整体性能
    • NAPI机制:混合「中断和轮询」的方式来接收网络包,当有网络包到达时,会通过 DMA 技术,将网络包写入到指定的内存地址,接着网卡向 CPU 发起硬件中断,当 CPU 收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数。
      • 中断处理函数:
        • 先「暂时屏蔽中断」,表示已经知道内存中有数据了,告诉网卡下次再收到数据包直接写内存就可以了,不要再通知 CPU 了,这样可以提高效率,避免 CPU 不停的被中断。
        • 接着,发起「软中断」,然后恢复刚才屏蔽的中断。
      • 软中断:内核中的 ksoftirqd 线程专门负责软中断的处理,当 ksoftirqd 内核线程收到软中断后,就会来轮询处理数据(采用poll方法)。
        • ksoftirqd 线程会从 Ring Buffer 中获取一个数据帧,用 sk_buff 表示,从而可以作为一个网络包交给网络协议栈进行逐层处理。
      • 网络协议栈:
        • 先进入到网络接口层,在这一层会检查报文的合法性,如果不合法则丢弃,合法则会找出该网络包的上层协议的类型,比如是 IPv4,还是 IPv6,接着再去掉帧头和帧尾,然后交给网络层。
        • 网络层,则取出 IP 包,判断网络包下一步的走向,比如是交给上层处理还是转发出去。当确认这个网络包要发送给本机后,就会从 IP 头里看看上一层协议的类型是 TCP 还是 UDP,接着去掉 IP 头,然后交给传输层。
        • 传输层取出 TCP 头或 UDP 头,根据四元组「源 IP、源端口、目的 IP、目的端口」 作为标识,找出对应的 Socket,并把数据放到 Socket 的接收缓冲区。
        • 应用层程序调用 Socket 接口,将内核的 Socket 接收缓冲区的数据「拷贝」到应用层的缓冲区,然后唤醒用户进程。

在这里插入图片描述

5. 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 的值来增加协议首部。

在这里插入图片描述

  • 到达网络层的主要工作:选取路由(确认下一跳的 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。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python】 如何将 datetime 转换为 date?

基本原理 在 Python 中,我们经常需要处理日期和时间。datetime 模块提供了丰富的功能来处理日期和时间。datetime 类型和 date 类型是 datetime 模块中的两个不同的类型。datetime 类型包含了日期和时间的信息,而 date 类型只包含日期信息。 当你需要将…

运筹学_7.博弈论(对策略)

文章目录 引言7.1 博弈论(对策论)的基本概念对策论有三个基本假设对策论的三个要素零和对策二人有限零和对策 7.2 矩阵对策矩阵对策数学模型 7.3 最优纯策略基本定理和性质最优纯策略基本定理最优纯策略基本性质 7.4 混合策略定义和性质混合策略的定义混合策略的性质 7.5 矩阵对…

德国RS SMA100A原装二手sma100a信号发生器6G

罗德与施瓦茨 SMA100A信号发生器,9 kHz 至 3 GHz 或 6 GHz R&S SMA100A 提供信号质量、速度和灵活性。R&S SMA100A 是一款高级模拟发生器,因其出色的特性而树立了标准。 它结合了卓越的信号质量和极高的设置速度。无论是在开发、生产、服务还是维…

GSEA的算法只考虑排序吗

其实这个问题很好回答&#xff0c;只需要运行如下代码&#xff0c;如下的基因列表是顺序是完全相同&#xff0c;并且我们只是做了最基础的变换 library(clusterProfiler) library(org.Hs.eg.db)data(geneList, package"DOSE")ego1 <- gseGO(geneList geneLi…

企业在现代市场中的战略:通过数据可视化提升财务决策

新时代&#xff0c;财务规划团队不仅仅是企业内部的一个部门&#xff0c;更是帮助企业做出明智决策和设定战略目标的中坚力量。在当今瞬息万变的商业环境中&#xff0c;财务专业人士需要具备应对挑战并引导企业走向成功的角色职能。企业领导者时常面临着数据压力&#xff0c;需…

如何快速部署上线项目

CSDN 的小伙伴们&#xff0c;大家好呀&#xff0c;我是苍何。 今天在群里面看到有小伙伴反馈说&#xff0c;面试的时候一被问到简历中的项目还没上线&#xff0c;就不继续问了&#xff0c;感觉挺奇葩的&#xff0c;要知道就校招来说&#xff0c;项目本身大部分都是练手的项目&…

基于 Potree.js 的 3D 点云展示

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 Potree.js 的 3D 点云展示 应用场景 本代码主要应用于需要在 Web 浏览器中展示和交互式浏览 3D 点云数据的场景。点云数据广泛应用于建筑、测绘、地理信息等领域&#xff0c;通过可视化点云&#xff0c;…

Mac下载docker

先安装homebrew Mac下载Homebrew-CSDN博客 然后输入以下命令安装docker brew install --cask --appdir/Applications docker 期间需要输入密码。输入完等待即可

解决uni-app progress控件不显示问题

官方代码&#xff1a; <view class"progress-box"><progress :percent"80" show-info activeColor"red" stroke-width"10" /> </view> 进度条并不在页面中显示&#xff0c;那么我们需要给进度条加上宽高style"…

面试Tip--java创建对象的四种方式

java创建对象一共有四种方式&#xff0c;但是我们在写代码的时候用的new 关键字偏多&#xff0c;像一些接口对接则是序列化创建对象偏多&#xff0c;今天我们来简单介绍下使用场景以及各个方式 1. 使用 new 关键字 这是最常见的创建对象的方式。 public class Example {priva…

vue-cl-service不同环境运行/build配置

概述 在项目开发过程中&#xff0c;同一个项目在开发、测试、灰度、生产可能需要不同的配置信息&#xff0c;所以如果能根据环境的不同来设置参数很重要。 vue项目的vue-cl-service插件也支持不同环境的不同参数配置和打包。 实现 新建不同环境配置文件 vue项目中的配置文件以…

人脸识别系统之静态人脸识别

人脸识别系统 一. 静态人脸识别 1. 人脸提取 1.1. 导入资源包 import tkinter as tk from tkinter import filedialog, messagebox from PIL import Image, ImageTk, ImageDraw import face_recognition import os import subprocess import sys注&#xff1a;进行人脸识别…

基于Docker+Jenkins实现自动部署SpringBoot+Maven项目

安装Docker随便根据其他教程安装即可&#xff0c;本文着重讲jenkins的安装与环境配置。 一、安装jenkins 1.运行命令搜索Jenkins docker search jenkins deprecated 是弃用的意思&#xff0c;第一条搜索记录就是告诉我们 jenkins 镜像已经弃用&#xff0c;让我们使用 jenkins…

ardupilot开发 --- 机载计算机-软件方案 篇

马儿跑马儿不吃草 0. 概述APSyncBlueOSDroneKitFlytOSMaverickROSRpanion-server结论 0. 概述 The Companion Computer software refers to the programs and tools that run on the Companion Computer. They will take in MAVLink telemetry from the Flight Controller and…

IGraph使用实例——图属性创建1

1 概述 在图论中&#xff0c;图由顶点&#xff08;vertices&#xff09;和边&#xff08;edges&#xff09;组成&#xff0c;可以是无向的或有向的。图的属性是用来提供关于图、顶点或边的额外信息的数据。以下是从图论角度对图的属性的描述&#xff1a; 图的属性&#xff08…

C++:特殊类设计和四种类型转换

一、特殊类设计 1.1 不能被拷贝的类 拷贝只会放生在两个场景中&#xff1a;拷贝构造函数以及赋值运算符重载&#xff0c;因此想要让一个类禁止拷贝&#xff0c;只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98&#xff1a; 1、将拷贝构造函数与赋值运算符重载只…

个人百度百科怎么创建

编辑百度词条是一个相对简单的流程&#xff0c;但需要注意的是&#xff0c;并不是所有的词条都可以编辑&#xff0c;部分锁定的词条是无法编辑的&#xff0c;但可以通过官方平台申请解封。以下百科优化网yajje分享是详细的步骤&#xff1a; 注册百度账号 首先&#xff0c;用户…

kernelbase.dll故障怎么处理的几种常见方法,有效的解决kernelbase.dll故障

kernelbase.dll是 Windows 操作系统的一个系统文件&#xff0c;它是 Windows NT 基本 API 客户端库的一部分。如果你遇到了kernelbase.dll出现故障的情况&#xff0c;这可能会导致软件崩溃或无法正常运行。下面是一些处理kernelbase.dll故障的常见方法。 重新启动计算机&#x…

企业百度百科词条怎么修改

企业百度百科词条的修改是提升企业网络形象的重要手段。以下是百科优化网yajj总结详细的修改步骤&#xff1a; 准备工作 注册并登录百度账号&#xff1a;这是进行词条编辑的前提]。熟悉百度百科编辑规则&#xff1a;了解内容要求、格式规范、参考资料等&#xff0c;有助于更好…

深入解析 Web 开发中的强缓存与协商缓存机制

在 Web 开发中,缓存机制是提高页面加载速度和用户体验的重要技术。缓存分为两种主要类型:强缓存和协商缓存。本文将详细介绍这两种缓存机制的原理、实现方式及其区别,并演示如何在 <meta> 元素中和 Nginx 服务器中进行缓存控制。 强缓存 强缓存(Strong Caching)是指…