Skip to main content

零拷贝

dma

direct memory access 直接内存访问 DMA 是一种硬件技术,它允许某些硬件子系统(如磁盘控制器、网卡、显卡)不经过 CPU 的干预,直接读写系统主内存 (RAM)。

传统非零拷贝常见

比如一个web服务器将文件通过网络发送给客户端

  1. 应用程序调用read()

  2. cpu 将磁盘数据复制到内核缓冲区(页缓冲区)(通过dma 给dma发送指令)

  3. cpu 将数据从内核缓冲区复制到用户缓冲区 第一次复制

  4. 应用程序调用write()

  5. cpu将数据从用户缓冲区复制到套接字缓冲区 第二次复制

  6. cpu将数据从套接字缓冲区复制到网卡(dma)

发生了俩次内核态和用户态之间的切换,以及俩次cpu参与的复制

零拷贝

内核直接将数据从页缓冲区复制到套接字缓冲区

mmap

mmap (Memory Mapped Files): 通过内存映射,让用户空间的一块虚拟地址指向内核空间的缓冲区。这样内核和用户进程共享同一块物理内存,完全消除了内核态与用户态之间的数据拷贝

常见的实现方案

mmap + write 通过内存映射(Memory Mapping),将内核缓冲区的数据直接映射到用户空间。

优势:内核与用户空间共享这块物理内存,减少了 1 次 CPU 拷贝。 切换:依然存在 4 次上下文切换。

sendfile Linux 提供的系统调用,直接在内核中将读缓冲区的数据传输到 Socket 缓冲区。

核心:数据不经过用户态。

优势:2 次上下文切换,最少仅需 2 次(或 3 次)拷贝。

sendfile + DMA Gather Copy 在硬件支持的情况下,进一步取消了内核内部的 CPU 拷贝。

流程:内核只将数据的描述符(长度、地址等)传给 Socket 缓冲区,DMA 直接从内核缓冲区抓取数据发送给网卡。

最终状态:整个过程 CPU 参与度为零