零拷贝是什么?sendfile 和 mmap 分别减少了哪些数据复制?
🧑💻 面试官:零拷贝是什么意思?
🙋♂️ 我:数据传输过程中一次复制都没有。
🧑💻 面试官:文件读出来发到网络,设备搬运数据也消失了吗?
🙋♂️ 我:不是,主要省某些 CPU 复制。
🧑💻 面试官:如果发送前要逐字节改内容,或者用了 TLS,还能直接套同一条路径吗?
零拷贝要说清省掉哪次复制、谁在搬运数据;它不是数据凭空到达。
面试速答(60 秒版)
零拷贝通常指减少某条 I/O 路径上的数据复制,尤其避免数据为了转发而在内核和用户缓冲之间来回搬运,不代表完全没有设备传输和任何复制。
普通 read 再 write 的文件转发,会经过用户缓冲。Linux sendfile 可以在内核侧完成相关转发,splice 可以借助管道连接描述符;mmap 是映射文件,并不自动等于完整网络发送零复制。
实际能省哪些步骤受系统、设备、协议栈和文件类型影响。数据需要修改、压缩或加密时,路径也可能变化。
选型先确认工作负载和具体接口,再测 CPU、吞吐、延迟及兼容性,同时处理部分发送、错误和文件生命周期。

知识点详解:把文件发出去,哪些搬运能省
先画普通路径,别先背四次复制
假设服务把一个文件原样发给客户端。常规 read 会让内容进入程序可访问的缓冲,随后 write 再把这些内容交给输出端。
如果程序既不检查也不修改内容,这个来回搬运可能只是转发的代价。零拷贝相关方案就是尝试减少这些不必要的步骤。
设备传输、页缓存、内核处理是否复制,以及具体复制次数,都要结合实现讨论。没有描述路径就直接报一个固定数字,很容易把不同系统混在一起。
sendfile 省用户缓冲绕行,mmap 管映射
sendfile 让文件内容在内核侧走向输出描述符。它适合相关支持条件下的文件转发,但仍可能只发送一部分,需要继续处理进度与错误。
mmap 则把文件内容映射到进程地址空间,让程序按地址访问。之后如何发到网络,仍是另一个步骤。
所以“mmap 就是 sendfile 的同义词”不对。一个侧重访问映射,一个侧重传输接口,能够减少的成本也不同。
splice 有条件,指针转交也需要生命周期
Linux splice 至少有一端是管道,可以在支持的描述符之间转移相关数据。内核可能通过页面引用减少实际内容复制,但不是所有端点和所有场景都能走理想路径。
如果输出端尚未消费完,相关源内容不能任意修改或释放。接口成功返回多少字节,也要以实际值为准。
减少复制不等于减少所有系统调用,更不等于不用维护缓冲状态。遇到不支持的类型,应有合理回退。
内容需要加工时,先确认优化还能成立
假设服务需要给文件每一行加前缀,那么程序确实要处理内容,原样转发的前提已经变了。压缩和 TLS 也会改变处理路径,具体还要看用户态、内核态或硬件能力。
对小文件、高缓存命中或瓶颈不在复制的负载,收益未必显著。测试需要相同网络、文件大小、缓存状态和并发条件。
回答重点不是宣布某 API 最快,而是说明它省了什么、在什么条件下省、什么时候不适合。
本题机制参考:sendfile 手册、splice 手册、mmap 手册。
面试官继续追问
零拷贝完全不用 CPU 吗?
不是。协议处理、调度、引用管理等仍消耗 CPU,省的是某些内容搬运。
sendfile 一次调用一定发完整个文件吗?
不保证。要处理返回字节数、非阻塞条件和错误。
TLS 一定不能用任何零拷贝优化吗?
也不能绝对化。具体要看 kTLS、设备和实现支持,不把普通用户态加密路径套成所有情况。
面试速记卡
- 零拷贝:减少特定路径的复制,不是完全无搬运。
- sendfile:相关文件转发避免用户缓冲绕行。
- mmap:文件映射,不自动完成网络零复制。
- splice:管道参与,受端点支持等约束。
- 验收:真实路径、部分发送、生命周期和负载测试。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
美团 · Java后端 · 社招
Kafka 的零拷贝机制怎样工作?(题意整理)
社招一年半面经分享 · 美团部分 ↗
历史面经,面试年份未明确;页面编辑于 2024-07-19