Linux是否有零拷贝?拼接或发送文件?

当拼接被引入时,在内核列表中讨论了sendfile是基于拼接重新实现的。拼接SLICE_F_MOVE的文档说明:

Attempt to move pages instead of copying. This is
only a hint to the kernel: pages may still be
copied if the kernel cannot move the pages from
the pipe, or if the pipe buffers don’t refer to
full pages. The initial implementation of this
flag was buggy: therefore starting in Linux 2.6.21
it is a no-op (but is still permitted in a
splice() call); in the future, a correct
implementation may be restored.

那么这是否意味着Linux对于写入套接字没有零拷贝的方法?或者这个固定在某些时候,没有人更新文档多年?在任何最新的3.x内核版本中,sendfile或splice都有零拷贝的实现?

由于Google对此查询没有任何答案,所以我为下一个可能的错误创建了一个stackoverflow问题,他们想知道如果使用vmsplice和splice或sendfile通过普通旧的写入有任何好处。

sendfile一直以来,仍然是零拷贝(假设硬件允许它,但通常情况下)。零拷贝是整个系统调用的首要任务。 sendfile现在被实现为拼接器周围的包装。

这表明拼接也是零拷贝,事实确实如此。至少在理论上,至少在某些情况下。问题在于弄清楚如何正确使用它,使其可靠地工作,因此它是零拷贝。文件是…稀疏,至少说。

特别地,如果页面被赋予“礼物”,则拼接仅适用于零拷贝,即,您不再拥有它们(正式地,但实际上您仍然这样做)。如果您将文件描述符简单地拼接到套接字上,那就是一个非问题,但是如果要从应用程序的地址空间或从一个管道到另一个管道拼接数据,这是一个很大的问题。目前还不清楚如何处理这些页面(以及何时)。该文件规定您可能不会随后触摸页面或与其做任何事情,永远不会。所以如果你遵循文档的信,你必须泄漏内存。
这显然是不正确的(不可能),但是当安全地重用或释放内存时,没有什么好的知道方式(至少你)。执行sendfile的内核会知道,因为一旦接收到TCP ACK,它就知道数据不再需要了。问题是,你永远不会看到一个ACK。所有你所了解的拼接已经返回的是数据已被接受发送(但你不知道它是否已被发送或接收,也不会发生这种情况)。
这意味着您需要通过手动确认(使用可靠的UDP)免费提供应用层,或假设如果对方发送请求的答案,那么它们显然必须已经获得请求。

另一件必须要管理的是有限的管道空间。默认值是非常小的,但即使你增加了大小,也不能只是天真地拼接任何大小的文件。 sendfile另一方面只会让你这样做,这很酷。

总而言之,sendfile是很好的,因为它只是工作,它的工作正常,你不需要关心上述任何细节。这不是灵丹妙药,但它确实是一个很好的补充。
我个人将远离拼接及其家庭,直到整个事情得到极大的改观,直到100%清楚你要做什么(何时)以及你不必做的事情。

无论如何,无论如何,大多数应用程序的真正有效的收益比普通的老笔记本是微不足道的。我记得几年前Torvalds先生的一些彬彬有礼的评论(当BSD有一种形式的写作,会做一些魔术,重新映射页面以获得零拷贝,而Linux没有),它指出制作副本通常没有任何问题,但是与网页玩弄的是[这里不会重复]。

http://stackoverflow.com/questions/24254098/does-linux-have-zero-copy-splice-or-sendfile

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:Linux是否有零拷贝?拼接或发送文件?