当vmsplice(4)
与它一起使用时SPLICE_F_GIFT
,承诺我的过程不会修改我提供的底层页面。据我所知,正常的工作流程是:
/*pseudo code don't kill me*/
void* page = memmap();
vmsplice(page, SPLICE_F_GIFT);
free(page);
但这要求我每次赠送页面时都使我的 TLB 无效。这很好地抵消了我因不复制数据而获得的任何性能增益。
那么我怎么知道内核是完毕与我的页面?我可以简单地不是释放页面吧?
我假设有这样的用例:
vmsplice -> pipe -> splice -> tcpsocket
我会等待响应,此时内核将刷新其SEND
缓冲区,我的页面将再次属于我的?
答案1
那么我怎么知道内核已经完成了我的页面呢?因为我根本无法释放该页面,对吗?
给内核的礼物。应用程序不得修改此内存曾经,否则页面缓存和磁盘上的数据可能会有所不同。
vmsplice -> 管道 -> 拼接 -> tcpsocket
我会等待响应,此时内核将刷新其发送缓冲区,我的页面将再次属于我的?
不
等到回复在您使用的协议中,确认已收到所有赠送的页面。然后你就会知道内核有刷新所有有天赋页面的发送缓冲区。
(顺便说一句,我不会假设页面的内容会保留下来。我想它可以就地进行 IPSec 加密)。
显然,还可以检索“套接字发送队列中未发送的数据量”,因此这是另一种方法。 https://stackoverflow.com/questions/6421771/vmsplice-and-tcp (当然,您不必按照此链接等待它降至 0,您可以在每个页面变得安全时重新使用它)。如果您没有填充内核发送队列,则需要进行轮询。 (当你是的时候,你只需同时重新检查选择()epoll() 告诉你还有更多空间可以写入数据)。
答案2
预期用途是 vmsplice 赠送 mmaped 页面,您无法在 vmsplice 之后更改这些页面,但可以 munmap 它们。