这篇文章主要介绍Linux有零拷贝吗?拼接或发送文件?,对于目前你搜索查找的问题还是具有挺好的参考价值,希望编程之家小编整理的这个内容对你们有所帮助。如有错误或未考虑完全的地方,望不吝讨教。
当引入拼接时,在内核列表上讨论了sendfile是基于拼接重新实现的。拼接SLICE_F_MOVE的文档强调:
尝试联通页面而不是复制。这只是内核的一个提示:假如内核未能从pipe道联通页面,或则pipe道缓冲区没有引用完整页面,页面仍可能被复制。这个标志的初始执行是错误的:因而,从Linux2.6.21开始,这是一个无操作(但依然准许在splice()调用中)。今后可能会恢复正确的施行。
这么这是否意味着Linux没有用于写入套接字的零拷贝方式?或则这是固定的,没有人更新多年的文件?在最新的3.x内核版本中,发送文件或拼接是否具有零拷贝实现?
因为微软没有回答这个查询,我为下一个可怜的schmuck创build一个stackoverflow的问题,谁想晓得是否有任何利益使用vmsplice和拼接或发送文件通过普通的旧写。
Java中的SendFile和transferTo
我怎样在POSIX中实现零拷贝机制?
“零复制networking”与“内核旁路”?
使用sendfile(),是否有可能晓得哪些时侯in_fd在EOF?
Linux套接字:零拷贝本地linux程序拷贝文件,TCP/IP远程
使用pipe道将数据发送到多个套接字,tee()和splice()
什么文件系统支持通过Linux拼接(2)拼接?
在Linux上可能是零拷贝的UDP打包?
带有和不带分散/集聚操作的零拷贝
哪些是vmsplice(2)的语义,有没有附赠?
sendfile仍然以来,一直是零拷贝(假定硬件容许它,但一般情况下)。零拷贝是把系统调用置于首位的全部要点。sendfile如今早已作为一个包装器来实现。
这表明splice也是零拷贝,事实的确这么。起码在理论上linux程序拷贝文件,起码在个别情况下。问题是认清楚怎样正确使用它linux删除命令,所以它可靠地工作,所以它是零拷贝。文件是少见的,起码可以说。
非常是,假如页面被赋于“礼物”,splice只能作为零拷贝,即你不再拥有它们(在方式上,但实际上你还是这样做)。假如你简单地将一个文件描述符拼接到一个套接字上,这是一个非问题,而且假如你想从你的应用程序的地址空间或从一个管线到另一个管线拼接数据,这是一个大问题。目前还不清楚怎样处理页面(以及何时)。文档强调linux删除文件夹,你之后可能不会触摸那些页面,或则对她们做任何事情,永远不会。所以,假如你根据文件的信函,你必须泄露显存。
这其实是不正确的(不可能),然而当重用或释放显存安全时,没有哪些好的方式可以晓得(起码对你来说!)。内核做一个sendfile会晓得,由于它一收到TCPACK就晓得数据不再须要了。问题是,你永远不会见到一个ACK。所有你晓得哪些时侯splice返回的是数据已被接受发送(但你不晓得它是否早已发送或接收,也不晓得哪些时侯会发生)。
这意味着你须要在应用层以某种形式弄清楚这一点,或则通过自动确认(可靠的UDP免费提供),或则假定假如对方发送了你的恳求的答案,她们或许必须得到恳求。
你必须管理的另一件事是有限的管线空间。默认是十分小的,但倘若你降低了大小,你不能天真地拼接任何大小的文件。另一方面sendfile只是让你这样做,这是很酷的。
总而言之,sendfile是挺好的,由于它正常工作,它运行良好,你不须要关心上述任何细节。这不是万能的,但肯定是一个挺好的补充。
我个人会远离splice和家庭,直至整个事情大大改善,直至100%清楚你必须做哪些(哪些时侯)以及哪些你何必做。
无论怎样,对于大多数应用程序来说,真正的,有效的利润比普通的旧的write是微不足道我记得几年前Torvalds先生的一些不礼貌的评论(当时BSD有一种write可以实现一些神奇的功能,重新映射页面以获得零拷贝,而Linux则没有)强调:一般没有任何问题,而且使用页面的方法是[这儿不再重复]。
按照2014-07-08拼接的相关指南页,我引用:
其实我们谈论复制,但一般会避开实际的复制。内核通过将管线缓冲区实现为内核显存页面的一组引用计数表针来实现这一点。内核通过创建指向页面的新表针(用于输出缓冲区)来创建页面的“副本”,并降低页面的引用计数:只复制表针,而不是缓冲区的页面。
为此,拼接在大多数情况下被记录为零拷贝。