10KB 以下的包开 MSG_ZEROCOPY,页固定和 completion notification 的开销会把你省掉的那次 memcpy 全部吃回去,甚至倒亏。splice 在小包场景同样如此——pipe buffer 的分配与引用计数操作,在 payload 不够大时就是净负担。这篇文章拆三种零拷贝机制各自绕过了哪次拷贝、代价结构长什么样,然后用实验数据画出收益曲线的拐点,并给出一张「包大小 × 发送频率 → 是否开零拷贝」的决策矩阵。传统发送路径:四次拷贝,两次上下文切换在讨论「零拷贝」之前,必须先弄清楚它省的是哪一次拷贝。传统路径用read()+write()把文件数据发到网络,数据在内存里走了四趟:┌──────────────┐ │ 用户进程 │ │ user buffer │ └──────┬───────┘ │ ② CPU copy (page cache → user buffer) │ ③ CPU copy (user buffer → socket buffer) ┌──────┴───────┐ │ 内核空间 │ │ page cache │──① DMA read (disk → page cache) │ socket buf │──④ DMA write (socket buf → NIC) └──────────────┘四次数据搬运里,① 和 ④ 是 DMA,CPU 不参与;真正烧 CPU 的是 ②