1181 words
6 minutes
linux零拷贝技术

传统拷贝与零拷贝技术#

操作系统处理IO,大致为以下两个步骤:

  • 数据取至内核空间(kernel space)
  • 内核空间传递数据到用户空间(user space)

IO大体又有两类,阻塞IO与非阻塞IO

传统拷贝流程#

首先来看传统拷贝操作,有以下步骤:

步骤操作描述详细说明
1发起read()调用用户态→内核态(第1次切换)
2内核发起DMA IO请求内核准备DMA传输
3磁盘DMA拷贝到内核缓冲区零CPU参与的数据传输
4内核缓冲区拷贝到用户缓冲区第1次CPU拷贝,调用返回后内核态→用户态(第2次切换)
5发起write()调用用户态→内核态(第3次切换)
6用户缓冲区拷贝到内核缓冲区第2次CPU拷贝
7内核缓冲区DMA拷贝到网卡零CPU参与的数据传输
8write()调用返回内核态→用户态(第4次切换)

开销总计:

  • 4次上下文切换
  • 2次CPU拷贝
  • 2次DMA拷贝

为什么要消除CPU拷贝?/为什么CPU拷贝非常昂贵?

  • CPU拷贝占用了大量的CPU时间片,且仅作数据搬运而不是复杂运算,我们认为这是”无意义劳动”
  • 大量内存块复制污染了CPU缓存,导致缓存命中降低
  • 涉及了内核态与用户态的切换,有明显的上下文成本

mmap#

MMap(Memory Map)是 Linux 中提供的一种将文件映射到进程地址空间的一种机制,我们可以将用户缓冲区和内核缓冲区进行映射处理,省略数据在内核缓冲区和用户缓冲区之间的 CPU 拷贝。
缺点:

  • 引入了新的CPU拷贝——内核缓冲区内部数据拷贝(PageCache到SocketBuffer)
  • 仍需2次系统调用(4次上下文切换)[此处只讨论mmap流程,实际可能涉及其他write操作]

sendFile#

sendFile()是一个用于高效地将文件数据从内核空间直接传输到网络套接字(Socket)上的系统调用,实现零拷贝。

其实现的核心思想在于,数据完全不进入用户空间,完全在内核空间进行传输,从而减少了内核缓冲区到用户缓冲区的CPU拷贝,同时压缩系统调用到1次,减少了2次用户态-内核态切换。但这也导致与mmap一样,引入了内核缓冲区内部的CPU拷贝。

在 Linux 2.4 后,sendfile引入了SG-DMA技术,对 DMA 拷贝加入了 scatter/gather 操作使之可以直接从内核空间缓冲区中读取数据到网卡,进而真正实现了零拷贝(该改进需要网卡硬件支持Scatter-Gather DMA)

splice#

Linux 2.6.17 引入 splice/tee/vmsplice,核心是利用 pipe buffer(页引用 + 引用计数) 在内核态搬运数据,通常避免用户态往返拷贝。

补充: “对部分文章表述 ‘与sendfile 方法不同,splice 不需要硬件支持’ 的理解与解释”
以”file → TCP socket”的典型路径为例,若网卡设备支持S-G DMA,二者路径高度相似
但如果网卡设备不支持S-G DMA(或中间路径被迫线性化),二者都会退化(引入额外的内核内拷贝)
splice的优势应该是实现了更通用的,尽可能零拷贝的通用接口,而sendfile在不是”file→socket”的场景就不合适,更加特化
此处不需要硬件支持应该是指:pipe通过pipe buffer增加页引用计数而不拷贝页的核心思想并不需要硬件支持

splice将数据从磁盘读取到内核缓冲区,在内核缓冲区和 socket 缓冲区之间建立管道来传输数据,避免了两者之间的 CPU 拷贝操作。
由于实现要求,splice的一端必须是管道,因此在file->socket的典型路径下,需要2次splice系统调用(file-pipe,pipe->socket),即4次用户态-内核态切换,0次CPU拷贝。

几种方式对比:#

拷贝机制系统调用CPU拷贝次数DMA拷贝次数上下文切换次数特点
传统拷贝方式read/write224消耗系统资源较多,效率较慢
mmapmmap/write124省略了用户缓冲区与内核缓冲区间的数据拷贝
sendfilesendfile122与 mmap 相比,减少了内存文件映射的步骤,但更特化
sendfile With DMA scatter/gathersendfile022需要网卡硬件支持S-G DMA,真正的零拷贝
splice(理想情况下)splice024真正的零拷贝,更泛用
linux零拷贝技术
https://fuwari.vercel.app/posts/linux零拷贝技术/
Author
7ac9d42
Published at
2025-12-13
License
CC BY-NC-SA 4.0