You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux中splice()的零拷贝实现原理及适用场景疑问

关于Linux零拷贝中splice()及传输场景的答疑

1. splice()如何实现零拷贝?

你之前的误解在于认为splice需要把数据实际拷贝到管道里——其实不是。splice的核心是在内核空间的缓冲区之间传递数据的引用(页指针+长度),管道在这里只是作为一个"中转容器"来承载这些引用,而非实际存储数据。

具体来说:

  • 当调用splice()从源文件描述符(比如磁盘文件)向管道写入时,内核并不会把数据从文件页缓存拷贝到管道缓冲区,而是直接将文件页缓存的页引用添加到管道的环形缓冲区中,全程没有CPU参与数据拷贝。
  • 接着调用splice()从管道向目标文件描述符(比如另一个文件、套接字)传输时,内核同样只是把管道里的页引用传递给目标的内核缓冲区,最终由DMA(直接内存访问)完成数据的物理传输,或者直接让目标地址空间映射这些页。

整个过程中,CPU只负责处理数据的位置、长度这类元信息,完全没有参与实际的数据拷贝操作,这就是splice实现零拷贝的关键。

2. 零拷贝是否仅支持文件与套接字之间的互传?

当然不是,零拷贝的适用场景远不止文件-套接字互传:

  • 早期版本的sendfile()确实只支持从文件页缓存到套接字缓冲区的传输,但Linux 2.6.33之后的sendfile()也支持文件到文件的零拷贝传输。
  • 而splice()的灵活性更高:
    • 支持文件到文件的零拷贝:通过管道中转两次splice调用,全程无CPU拷贝。
    • 支持套接字到文件的零拷贝:比如把网络接收的数据直接写入磁盘,无需经过用户缓冲区。
    • 甚至支持套接字到套接字的零拷贝:可以通过两个管道配合splice()和tee()系统调用,实现网络数据的转发,全程数据都在内核空间流转,不经过用户态。

简单来说,只要是能通过内核缓冲区交互的场景,都可以借助对应的零拷贝系统调用实现无CPU拷贝的数据传输。

内容的提问来源于stack exchange,提问作者Aritra Sur Roy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:20:44