零拷贝
dma
direct memory access 直接内存访问 DMA 是一种硬件技术,它允许某些硬件子系统(如磁盘控制器、网卡、显卡)不经过 CPU 的干预,直接读写系统主内存 (RAM)。
传统非零拷贝常见
比如一个web服务器将文件通过网络发送给客户端
-
应用程序调用read()
-
cpu 将磁盘数据复制到内核缓冲区(页缓冲区)(通过dma 给dma发送指令)
-
cpu 将数据从内核缓冲区复制到用户缓冲区 第一次复制
-
应用程序调用write()
-
cpu将数据从用户缓冲区复制到套接字缓冲区 第二次复制
-
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 参与度为零