Linux之【网络I/O】前世今生(一)

server/2025/2/12 12:07:51/

在 Linux之【磁盘I/O】前世今生 一文中,我们介绍了文件I/O 的细节。本文将继续介绍网络I/O的内容。

一、 基本概念

介绍网络I/O前,先了解一些基本概念。

1.1、上下文

CPU 寄存器,是CPU内置的小容量、速度极快的内存。程序计数器,是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。二者是 CPU 在运行任何任务时,必须依赖的环境,记为上下文

1.2、上下文切换

运行新的任务时需把当前任务的上下文(也就是CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器中,最后再跳转到程序计数器所指的新位置,运行新任务。

所以执行不同的程序,即进程切换时会发生上下文切换,线程切换也一样。

操作系统和用户程序是两个不同的程序,前者运行在内核态,后者运行在用户态,所以,内核态和用户态的切换一定会发生上下文切换,进程从用户态到内核态的转变,需要通过系统调用(调用操作系统)来完成。系统调用的过程,会发生CPU上下文的切换。

CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。

1.3、Linux I/O读写方式

  • 轮询
  • 基于死循环对 I/O 端口进行不断检测;
  • 需要CPU参与。
  • I/O 中断
  • 当数据到达时,磁盘主动向 CPU 发起中断请求,由 CPU 自身负责数据的传输过程;
  • 需要CPU参与。
  • DMA(Direct Memory Access,直接存储器访问) 传输则在 I/O 中断的基础上引入了 DMA 磁盘控制器,由 DMA 磁盘控制器负责数据的传输,降低了 I/O 中断操作对 CPU 资源的大量消耗;
  • DMA本质上是一块主板上独立的芯片,允许外设设备和内存存储器之间直接进行IO数据传输,其过程不需要CPU的参与;
  • 每个 I/O 设备里面都有自己的 DMA 控制器,如网卡、声卡、显卡、磁盘控制器等;
  • CPU 除了在数据传输开始和结束时做一点处理外(开始和结束时候要做中断处理),在传输过程中 CPU 可以继续进行其他的工作。这样在大部分时间里,CPU 计算和 I/O 操作都处于并行操作,使整个计算机系统的效率大大提高。

二、 网络I/O

2.1、传统网络I/O

以网络传输文件为例,需要经历步骤如下图所示:

在这里插入图片描述

read + write 组合:
  • 涉及上下文切换 4 次
    • read 调用发起,图示(1);
    • read 调用返回,图示(4);
    • write 调用发起,图示(5);
    • write 调用返回,图示(8);
  • 数据拷贝 4 次
    • 数据读取:
      • 磁盘拷贝到 page Cache,图示(2)DMA拷贝;
      • page Cache 拷贝到程序Buffer,图示(3)CPU拷贝;
    • 数据写入:
      • 程序Buffer 拷贝到Socket缓存区,图示(6)CPU拷贝;
      • Socket缓存区拷贝到网卡,图示(7)DMA拷贝;
  • 注意上图拷贝数据步骤(2)、(3)、(6)、(7)区别:(3)和(6)是CPU拷贝,(2)和(7)是DMA拷贝。

2.2、优化传统网络I/O

上文提到传统网络I/O性能最大的瓶颈在于:

所以我们优化的主要方向就是这两个维度:减少数据拷贝次数和上下文切换次数。

2.2.1、减少数据拷贝次数

2.2.1.1、mmap(Memory Map,内存映射)

仔细观察,数据没有必要拷贝到程序 Buffer 中,我们可以采用 mmap(memory map,内存映射) 技术,将程序 Buffer 映射到内核 Page Cache,从而避免数据在内核态和用户态之间相互拷贝。

在这里插入图片描述

mmap + write 组合替代read + write 组合后:
  • 涉及上下文切换 4 次

    mmap 调用和返回、 write 调用和返回。

  • 数据拷贝 3 次
    • 1次CPU拷贝;
    • 2次DMA拷贝。

Java NIO有一个MappedByteBuffer的类,可以用来实现内存映射。它的底层是调用了Linux内核的mmap的API。

2.2.2、减少上下文切换次数

sendfile_68">2.2.2.1、sendfile

目前为止,我们已经通过 mmap 技术成功的将数据拷贝次数减少了1次;但还是涉及4次上下文切换,我们可以将之前的两次系统调用(read、write)合并为一次,记为 sendfile(Linux 内核版本 2.1开始提供), sendfile 不会拷贝数据到用户态,直接在内核态工作。

在这里插入图片描述

sendfile__mmap__write__73">用 sendfile 来替代 mmap + write 组合后:

java 中 FileChannel#transferTo() 底层调用的正是sendfile

sendfile__SGDMA_80">2.2.2.2、sendfile + SG-DMA

linux 2.4版本之后,对sendfile做了优化升级,引入SG-DMA(需要硬件支持) 技术,其实就是对DMA拷贝加入了分散/收集(scatter/gather)操作,它可以直接从内核空间缓冲区中将数据读取到网卡。

SG-DMA
CPU 将 Page Cache 中的数据描述信息(内存地址和偏移量)记录到socket缓冲区,由 SG-DMA 根据这些将数据从Page Cache拷贝到网卡,相比之前版本减少了一次CPU拷贝的过程。

在这里插入图片描述

sendfile___SGDMA__86">sendfile + SG-DMA 组合:
2.2.2.3、splice

sendfile 只适用于将数据从文件拷贝到 socket 套接字上,且sendfile + SG-DMA组合还需要硬件的支持,这也限定了它的使用范围。

Linux在 2.6.17 版本引入 splice 系统调用,不仅不需要硬件支持,同时还支持实现了两个普通文件之间数据流动;

也就是说 splice 不仅实现了sendfile + SG-DMA组合的功能,还扩大了使用范围。后续 sendfile 经过优化,底层也直接调用了 splice 来实现功能。

splice 系统调用可以在Page CacheSocket 缓存区之间建立管道(pipeline),从而避免了两者之间的CPU拷贝。

在这里插入图片描述

splice__102">splice

三、零拷贝(Zero-copy)

拷贝方式系统调用DMA拷贝次数CPU拷贝次数上下文切换次数
传统方式read + write224
内存映射mmap + write214
sendfilesendfile212
sendfile + SG-DMAsendfile202
splicesplice202

至此,我们将不断的将传统I/O进行改进,将CPU拷贝次数逐步降低为0。我们把改进后的拷贝方式,统称为零拷贝(Zero-copy),官方定义如下:

零拷贝是指计算机执行I/O操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及CPU的拷贝时间。它是一种I/O操作优化技术。

从这个定义来看,在 Linux之【磁盘I/O】前世今生 中提到的 直接I/O (从硬盘直接拷贝数据到用户缓存,不需要OS Cache)同样属于零拷贝;此外,还有写时复制COW(copy on write) 同样也属于零拷贝

Linux 前世今生系列文章:


http://www.ppmy.cn/server/167049.html

相关文章

MySQL 中可以通过添加主键来节省磁盘空间吗?(译文)

从历史上看,MySQL 不需要在表上定义显式主键,直到今天默认都是这样。不过,这种要求是通过两种复制方法施加的:组复制和 Percona XtraDB 集群 (PXC),默认情况下不允许使用没有主键的表。对于缺少…

独立站赋能反向海淘:跨境代购系统的用户体验与支付解决方案

随着全球化的推进以及消费者对海外商品多样化需求的增长,独立站赋能的反向海淘模式愈发火热,其中跨境代购系统的用户体验与支付解决方案起着关键作用。 一、跨境代购系统的用户体验 界面友好性 独立站的页面设计需要简洁、直观,方便用户快速…

innovus如何分步长func和dft时钟

在Innovus工具中,分步处理功能时钟(func clock)和DFT时钟(如扫描测试时钟)需要结合设计模式(Function Mode和DFT Mode)进行约束定义、时钟树综合(CTS)和时序分析。跟随分…

.net framework 4.5 的项目,用Mono 部署在linux

步骤 1:安装 Mono 更新包列表: 首先,更新 Ubuntu 的包列表以确保获取最新的软件包信息。 sudo apt update 安装 Mono: 安装 Mono 完整版(mono-complete),它包含了运行 .NET 应用程序所需的所有…

1.4 AOP编程范式

1.4 AOP编程范式 1.4.1 代理模式底层原理剖析(字节码级解析) 代理机制对比矩阵: | 维度 | JDK动态代理 | CGLIB字节码增强 | |----------------|--------------------------------|---------…

SAP-SD信用管理实施总结

SAP-SD 信用管理实施总结 摘要 信用管理是SAP-ERP系统(以下简称SAP) SD模块中的子模块,主要用于有效平衡赊销模式和资金回笼这两个业务层面之间的矛盾。本文档以信用管理在SAP系统中的实现方法为出发点,结合业务背景,以…

C语言简单练习题

文章目录 练习题一、计算n的阶乘bool类型 二、计算1!2!3!...10!三、计算数组arr中的元素个数二分法查找 四、动态打印字符Sleep()ms延时函数system("cls")清屏函数 五、模拟用户登录strcmp()函数 六、猜数字小游戏产生一个随机数randsrandRAND_MAX时间戳time() 示例 …

Deepseek使用途径以及Prompt 提示词编写原理

Deepseek使用途径以及Prompt 提示词编写原理 1.Deepseek使⽤途径 1.官⽹及APP ⽹址: deepseek.com 及移动应⽤(iOS/Android) 特征:完整版R1模型,⽀持深度搜索,但⽬前因流量⼤常遇到服务器繁忙问题。 2.…