传统 read + write 发送文件要走四步:DMA 把磁盘数据读入内核页缓存、CPU 拷贝到用户缓冲区、CPU 从用户缓冲区拷到 socket 缓冲区、DMA 发到网卡——4 次拷贝 + 4 次用户/内核上下文切换,而数据在用户态根本没被加工,纯属白搬。零拷贝的目标就是砍掉用户态这一进一出。

主要技术路线:1)sendfile(Linux)——一次系统调用让数据在内核内从页缓存直达 socket 缓冲区,2 次拷贝 2 次切换;支持 SG-DMA 的网卡连内核内的拷贝都能省(DMA gather 直接收集页缓存数据),接近真零拷贝。2)mmap + write——把文件映射到用户地址空间,用户缓冲与页缓存共享物理页,省一次 CPU 拷贝,适合需要在用户态轻度加工的场景。3)splice——内核管道在两个 fd 间移动数据。落地案例:Kafka 用 sendfile 把日志段直发网络(吞吐的关键设计之一)、Nginx 静态文件 sendfile on、Netty 的 FileRegion。追问方向:零拷贝与用户态协议栈(DPDK)的关系、为什么加密(TLS)会破坏零拷贝(数据必须进用户态处理,kTLS 把加密下沉内核是解法)、Java 的 transferTo 何时退化为普通拷贝。

(约 450 字)