java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
1 I/O 中断原理
在 DMA 技术出现之前,应用程序与磁盘之间的 I/O 操作都是通过 CPU 的中断完成的。
- 用户进程向 CPU 发起 read 系统调用读取数据,由用户态切换为内核态,然后一直阻塞等待数据的返回。
- CPU 在接收到指令以后对磁盘发起 I/O 请求,将磁盘数据先放入磁盘控制器缓冲区。
- 数据准备完成以后,磁盘向 CPU 发起 I/O 中断。
- CPU 收到 I/O 中断以后将磁盘缓冲区中的数据拷贝到内核缓冲区,然后再从内核缓冲区拷贝到用户缓冲区。
- 用户进程由内核态切换回用户态,解除阻塞状态,然后等待 CPU 的下一个执行时间钟。
可以看到,整个数据的传输过程,都要需要 CPU 亲自参与搬运数据的过程,而且这个过程,CPU 是不能做其他事情的。
假如通过千兆网卡或者磁盘传输大量数据时,使用 CPU 来拷贝的话,对 CPU 资源是种极大的消耗。
2 DMA 方式
DMA 的全称是直接内存访问(Direct Memory Access),是一种硬件设备绕开 CPU 独立直接访问内存的机制。
目前支持 DMA 的硬件包括:网卡、声卡、显卡、磁盘控制器等。
基于 DMA 访问方式,系统主内存于硬盘或网卡之间的数据传输可以绕开 CPU 的全程调度,数据搬运的工作交给 DMA 控制器,在传输过程中,CPU 可以继续处理其他的工作,提升系统的资源利用率。
- 用户进程向 CPU 发起 read 系统调用读取数据,用户态切换为内核态,然后一直阻塞等待数据的返回。
- CPU 在接收到指令以后对 DMA 磁盘控制器发起调度指令。
- DMA 磁盘控制器对磁盘发起 I/O 请求,将磁盘数据先拷贝到磁盘控制器缓冲区,CPU 全程不参与此过程。
- 数据读取完成后,DMA 磁盘控制器会接受到磁盘的通知,将数据从磁盘控制器缓冲区拷贝到内核缓冲区。
- DMA 磁盘控制器向 CPU 发出数据读完的信号,由 CPU 负责将数据从内核缓冲区拷贝到用户缓冲区。
- 用户进程由内核态切换回用户态,解除阻塞状态,然后等待 CPU 的下一个执行时间钟。
3 传统 I/O 方式
为了理解零拷贝技术的思路,首先了解一下传统 I/O 方式存在的问题。
Linux 系统中,传统的访问方式是通过 write() 和 read() 两个系统调用实现的,通过 read() 函数读取文件到到缓存区中,然后通过 write() 方法把缓存中的数据输出到网络端口 。
下图分别对应传统 I/O 操作的数据读写流程,整个过程涉及 4 次上下文切换、 2 次 CPU 拷贝、2 次 DMA 拷贝总共 4 次拷贝。
- 4 次上下文切换
因为发生了两次系统调用,一次是 read()
,一次是 write()
,用户程序向内核发起系统调用时,CPU 将用户进程从用户态切换到内核态;当系统调用返回时,CPU 将用户进程从内核态切换回用户态。
- 4 次 数据拷贝
- 第一次 DMA 拷贝,将磁盘上的数据拷贝到操作系统内核的缓冲区 ;
- 第二次 CPU 拷贝,将内核缓冲区的数据拷贝到用户的缓冲区里;
- 第三次 CPU 拷贝,将用户缓冲区的数据,拷贝到内核 Socket 缓冲区;
- 第四次 DMA 拷贝,将内核 Socket 缓冲区的数据拷贝到网卡的缓冲区。
综上,想要提升文件传输的性能,因此我们需要减少「上下文切换 」和「数据拷贝」的次数。
3 零拷贝方式
零拷贝技术实现的方式通常有 2 种:mmap + write 、sendfile、sendfile + DMA scatter-gather 。
3.1 mmap + write
mmap 是 Linux 提供的一种内存映射文件的机制,它实现了将内核中读缓冲区地址与用户空间缓冲区地址进行映射,从而实现内核缓冲区与用户缓冲区的共享。
基于 mmap + write 系统调用的零拷贝方式,整个拷贝过程会发生 4 次上下文切换,1 次 CPU 拷贝和 2 次 DMA 拷贝。
用户程序读写数据的流程如下:
- 用户进程通过 mmap() 函数向内核发起系统调用,上下文从用户态切换为内核态。
- 将用户进程的内核空间的读缓冲区与用户空间的缓存区进行内存地址映射。
- CPU 利用 DMA 控制器将数据从主存或硬盘拷贝到内核空间的读缓冲区。
- 上下文从内核态切换回用户态,mmap 系统调用执行返回。
- 用户进程通过 write() 函数向内核发起系统调用,上下文从用户态切换为内核态。
- CPU 将读缓冲区中的数据拷贝到的网络缓冲区。
- CPU 利用 DMA 控制器将数据从网络缓冲区(socket buffer)拷贝到网卡进行数据传输。
- 上下文从内核态切换回用户态,write 系统调用执行返回。
mmap 的拷贝虽然减少了 1 次 CPU 拷贝,提升了效率,但也存在一些隐藏的问题。
当 mmap 一个文件时,如果这个文件被另一个进程所截获,那么 write 系统调用会因为访问非法地址被 SIGBUS 信号终止,SIGBUS 默认会杀死进程并产生一个 coredump,服务器可能因此被终止。
3.2 sendfile
sendfile 系统调用在 Linux 内核版本 2.1 中被引入,目的是简化通过网络在两个通道之间进行的数据传输过程。
通过 sendfile 系统调用,数据可以直接在内核空间内部进行 I/O 传输,从而省去了数据在用户空间和内核空间之间的来回拷贝。
sendfile 系统调用的引入,不仅减少了 CPU 拷贝的次数,还减少了上下文切换的次数,它的伪代码如下:
基于 sendfile 系统调用的零拷贝方式,整个拷贝过程会发生 2 次上下文切换,1 次 CPU 拷贝和 2 次 DMA 拷贝。
用户程序读写数据的流程如下:
- 用户进程通过 sendfile() 函数向内核发起系统调用,上下文从用户态切换为内核态。
- CPU 利用 DMA 控制器将数据从主存或硬盘拷贝到内核空间的读缓冲区。
- CPU 将读缓冲区中的数据拷贝到的网络缓冲区。
- CPU 利用 DMA 控制器将数据从网络缓冲区拷贝到网卡进行数据传输。
- 上下文从内核态切换回用户态,sendfile 系统调用执行返回。
相比较于 mmap 内存映射的方式,sendfile 少了 2 次上下文切换,但是仍然有 1 次 CPU 拷贝操作。
3.3 sendfile + DMA gather copy
Linux 2.4 版本的内核对 sendfile 系统调用进行修改,为 DMA 拷贝引入了 gather 操作。
它将内核空间的读缓冲区中对应的数据描述信息(内存地址、地址偏移量)记录到相应的网络缓冲区中,由 DMA 根据内存地址、地址偏移量将数据批量地从读缓冲区拷贝到网卡设备中,这样就省去了内核空间中仅剩的 1 次 CPU 拷贝操作。
在硬件的支持下,sendfile 拷贝方式不再从内核缓冲区的数据拷贝到 socket 缓冲区,取而代之的仅仅是缓冲区文件描述符和数据长度的拷贝,这样 DMA 引擎直接利用 gather 操作将页缓存中数据打包发送到网络中即可,本质就是和虚拟内存映射的思路类似。
基于 sendfile + DMA gather copy 系统调用的零拷贝方式,整个拷贝过程会发生 2 次上下文切换、0 次 CPU 拷贝以及 2 次 DMA 拷贝,用户程序读写数据的流程如下:
- 用户进程通过 sendfile() 函数向内核发起系统调用,上下文从用户态切换为内核态。
- CPU 利用 DMA 控制器将数据从主存或硬盘拷贝到内核空间的读缓冲区。
- CPU 把读缓冲区的文件描述符(file descriptor)和数据长度拷贝到网络缓冲区。
- 基于已拷贝的文件描述符和数据长度,CPU 利用 DMA 控制器的 gather/scatter 操作直接批量地将数据从内核的读缓冲区拷贝到网卡进行数据传输。
- 上下文从内核态切换回用户态,sendfile 系统调用执行返回。
5 写到最后
无论是传统 I/O 拷贝方式还是引入零拷贝的方式,2 次 DMA 拷贝是都少不了的,因为两次 DMA 都是依赖硬件完成的。
| 拷贝方式 | CPU拷贝 | DMA拷贝 | 系统调用 | 上下文切换 | | -------------------------- | ------- | ------- | ------------ | ---------- | | 传统方式(read + write) | 2 | 2 | read / write | 4 | | 内存映射(mmap + write) | 1 | 2 | mmap / write | 4 | | sendfile | 1 | 2 | sendfile | 2 | | sendfile + DMA gather copy | 0 | 2 | sendfile | 2 |
RocketMQ 选择了 mmap + write 这种零拷贝方式,适用于业务级消息这种小块文件的数据持久化和传输;
而 Kafka 采用的是 sendfile 这种零拷贝方式,适用于系统日志消息这种高吞吐量的大块文件的数据持久化和传输。
但是值得注意的一点是,Kafka 的索引文件使用的是 mmap + write 方式,数据文件使用的是 sendfile 方式。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
美国大选尘埃落定,AI“猜”对了,你呢?
美国东部时间11月6日凌晨1点,随着阿拉斯加州的最后一个投票点关闭,美国大选选举日所有投票结束。美国共和党总统候选人特朗普在弗洛里达州西棕榈滩发表演讲,宣布在2024年总统选举中以277票赢得本次大选,正式重返白宫,成为美国第47任总统。随着大选的尘埃落定,我们不仅见证了政治舞台上的激烈角逐,还目睹了人工智能(AI)从预测选情到大选后的行业变革,在这场全民盛事中扮演的不可忽视的角色。 特朗普胜选演讲 美国大选中的AI预测 在这场选情胶着、竞争激烈的选举中,不仅美国民众,全世界都在关注谁将入主白宫。今年,除了传统民意调查和专家分析,AI技术也加入了预测的行列。 ●AI Agent帮助理解选民意向变化 在6月举行的纽约州联邦众议院选举初选中,中间派候选人乔治·拉蒂默以58.7%的得票率战胜了现任众议员贾马尔·鲍曼,后者获得了41.3%的选票。而在官方数据公布之前,AI公司Aaru已经进行了一次精准的民意预测,其预测结果与实际结果的误差仅为371票。与众不同的是,Aaru的预测并没有依赖传统的民意调查,而是通过分析人口普查数据来实现的。 据Aaru公司的联合创始人卡姆·芬克(Ca...
- 下一篇
HarmonyOS NEXT火热公测中,首批100万名公测用户速来领取多重权益!
HarmonyOS NEXT火热公测中,首批100万名公测用户速来领取多重权益!华为视频、华为阅读、音乐、主题、云空间、天际通等应用会员一应俱全;还有爱奇艺、哔哩哔哩、芒果TV、WPS、喜马拉雅、优酷六大应用的会员季卡6选2,无论是海量影视综艺的沉浸观赏,还是悦耳听书与高效办公的轻松享受,一切精彩尽在其中。 询问AI
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,7,8上安装Nginx,支持https2.0的开启