Zero-Copy 技术

介绍 Linux 中的零拷贝技术。从 Fuse 学习 中独立出来。

read、write 接口

从普通文件 read,涉及两次复制:

  • 从磁盘通过 DMA 读到内核的 page cache
    这里的 page cache 机制也是一种 kernel buffer,但专门提供给磁盘文件的。
  • 从内核的 page cache 复制到 user buffer

从套接口读数据:

  • 从网卡通过 DMA 直接写入 kernel buffer
  • 从 kernel buffer 复制到 user buffer

注意,在使用 DMA 之前,磁盘读出来的数据会放到一个寄存器里面,然后通过中断通知 CPU 把数据写到临时的内存中攒批,最后写到 page cache 中。但是该方式性能太差,早已经淘汰了。

读数据过程:

  • 调用 read() 函数陷入内核,第一次 context switch
  • DMA 控制器将数据从磁盘拷贝到 kernel buffer,这是第一次 DMA 拷贝
  • CPU 将数据从 kernel buffer 复制到 user buffer,这是第一次 CPU 拷贝
  • CPU 完成拷贝之后,read() 函数返回到用户态,第二次 context switch

写过程类似。

mmap

把 kernel space 的页映射到 user space,所以可以避免从 kernel space 到 user space 的一次复制。
关于 mmap 可以见 内存领域知识

sendfile

原始 sendfile

sendfile 将数据从磁盘读到内核的 page cache,然后将 page cache 复制到 socket 的 buffer 中。

它的好处是减少了 syscall 的次数。将 read + write 或者 mmap + write 打包了。
但是,仍然需要 2 次 DMA 拷贝和 1 次 CPU 拷贝。

sendfile + DMA 优化

将从 page cache 到 socket buffer 的那一次 CPU 拷贝去掉了。DMA 可以直接从 page cache 拷贝数据到网卡里面。

splice