详解零拷贝原理

前言

总所周知,磁盘读写速度令人堪忧,特别是机械硬盘,读写速度相差内存 10 倍以上,所以针对优化磁盘的技术非常的多,比如零拷贝、直接 I/O、异步 I/O 等等,下面我们就分几个点来讲讲零拷贝技术。

DMA技术是什么?

直接内存访问(Direct Memory Access 技术,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务

在没有 DMA 技术前,I/O 的过程是这样的:

  • CPU发起IO指令给磁盘
  • 磁盘收到指令,把数据放入磁盘缓冲区,然后产生一个中断;
  • CPU 收到中断信号后,把磁盘缓冲区的数据读进内核缓冲区,然后再把内核缓冲区写入到用户缓冲区,而在数据传输的期间 CPU 是无法执行其他任务的

有 DMA 技术之后,I/O 的过程是这样的:

可以看到, 整个数据传输的过程,CPU 不再参与数据搬运的工作,而是全程由 DMA 完成,大大提高了CPU的性能。

传统IO

传统文件传输,将磁盘上的文件读取出来,然后通过网络协议发送给客户端。

流程: 磁盘->内核缓冲区->用户缓存区->socket缓冲区->网卡缓冲区

分析: 4次拷贝(2次DMA,2次CPU),4次状态切换,因为发生了两次系统调用,一次是 read() ,一次是 write(),每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态

结论: 想提高文件传输的性能,就需要减少「用户态与内核态的上下文切换」和「内存拷贝」的次数

  • 要想减少上下文切换到次数,就要减少系统调用的次数
  • 在用户空间我们并不会对数据「再加工」,所以数据实际上可以不用搬运到用户空间,因此用户的缓冲区是没有必要存在的

mmap内存映射

针对传统IO的缺陷,一个优化方案就是通过mmap系统替代read系统调用,这个函数的作用是让用户缓冲区共享内核缓冲区

流程: 硬盘->内核缓冲区=用户缓存区->socket缓冲区->网卡缓冲区

分析: 3次拷贝,4次状态切换,因为mmap系统调用也是2次状态切换

结论: 但这还不是最理想的零拷贝,因为仍然需要通过 CPU 把内核缓冲区的数据拷贝到 socket 缓冲区里,而且仍然需要 4 次上下文切换

sendFile

在 Linux 内核版本 2.1 中,提供了一个专门发送文件的系统调用函数 sendfile(),它可以替代前面的 read()write() 这两个系统调用,这样就可以减少一次系统调用,也就减少了 2 次上下文切换的开销。

流程: 硬盘->内核缓冲区->socke缓冲区->网卡缓冲区

分析: 3次拷贝,2次状态切换,只有一次sendFile系统调用,2次状态切换

优化: linux2.4后续优化:硬盘->内核缓冲区->网卡缓冲区

2次拷贝,2次状态切换,源头到目标,零拷贝,全程没有通过 CPU 来搬运数据,所有的数据都是通过 DMA 来进行传输的,这就是真正意义上的零拷贝

应用场景

事实上,Kafka 这个开源项目,就利用了「零拷贝」技术,从而大幅提升了 I/O 的吞吐率,这也是 Kafka 在处理海量数据为什么这么快的原因之一。

如果你追溯 Kafka 文件传输的代码,你会发现,最终它调用了 Java NIO 库里的 transferTo方法:

arduino 复制代码
@Overridepublic   
long transferFrom(FileChannel fileChannel, long position, long count) throws IOException {   
    return fileChannel.transferTo(position, count, socketChannel);  
}

如果 Linux 系统支持 sendfile() 系统调用,那么 transferTo() 实际上最后就会使用到 sendfile() 系统调用函数。

相关推荐
fengyehongWorld2 分钟前
Linux journald与journalctl命令
linux·运维·服务器
米高梅狮子6 分钟前
1. Cockpit 管理服务器
linux·运维·服务器
一颗青果6 小时前
HTTP协议详解
linux·网络·网络协议·http
广州灵眸科技有限公司9 小时前
瑞芯微(EASY EAI)RV1126B CAN使用
linux·网络·单片机·嵌入式硬件
魂万劫11 小时前
如何在虚拟机VM上|Linux环境内安装windows
linux·运维·服务器·windows
序属秋秋秋11 小时前
《Linux系统编程之进程控制》【进程等待】
linux·c语言·c++·进程·系统编程·进程控制·进程等待
zfj32111 小时前
top 命令中的 wa (IO wait) 指标,理论上几乎完全是由磁盘IO(包括swap)引起的,而不是网络IO
linux·网络·top·iowait
Xの哲學11 小时前
Linux网卡注册流程深度解析: 从硬件探测到网络栈
linux·服务器·网络·算法·边缘计算
用户61354114601612 小时前
libicu-62.1-6.ky10.x86_64.rpm 安装步骤详解(麒麟V10系统)
linux
秋42713 小时前
防火墙基本介绍与使用
linux·网络协议·安全·网络安全·架构·系统安全