引言:数据搬运的隐形成本

在网络编程中,「数据拷贝」是性能杀手之一。一个典型的 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,                        
                    
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部