引言:数据搬运的隐形成本
在网络编程中,「数据拷贝」是性能杀手之一。一个典型的 HTTP 文件服务器,数据从磁盘到网卡需要经历4 次拷贝 4 次上下文切换:磁盘 → 内核缓冲区 → 用户缓冲区 → Socket 缓冲区 → 网卡。面对 10Gbps 的流量,CPU 可能将 70% 的时间浪费在数据搬运上。
零拷贝技术的终极目标是消除这些不必要的拷贝。本文将逐一剖析 mmap、sendfile、splice 和 io_uring 四大机制,帮你构建真正高性能的网络服务。
一、传统 I/O 路径剖析
不优化的文件传输路径:
用户态 内核态
│ │
│ read() │
├──────────────────► │ DMA 拷贝:磁盘 → Page Cache(内核缓冲区)
│ │
│ │ CPU 拷贝:内核缓冲区 → 用户态 buffer
│ 返回数据 │
│ ◄──────────────── │
│ │
│ write() │
├──────────────────► │ CPU 拷贝:用户态 buffer → Socket 缓冲区
│ │
│ │ DMA 拷贝:Socket 缓冲区 → 网卡
│ 返回 │
│ ◄──────────────── │
可以看到,中间的两次 CPU 拷贝完全是「无意义搬运」——数据最终既不由用户态修改,也不经过任何处理。
二、mmap write:减少一次拷贝
mmap() 将内核态的 Page Cache 直接映射到用户态地址空间,省去「内核缓冲区 → 用户 buffer」这一步 CPU 拷贝:
int fd = open("data.bin", O_RDONLY);
struct stat sb;
fstat(fd,

发表评论 取消回复