Linux零拷贝:使用vmsplice在两个进程之间传输内存页面

时间:2012-05-17 16:21:14

标签: c linux virtual-memory splice

目前,我正在努力了解splice / vmsplice的价值。关于IPC的用例,我在stackoverflow上偶然发现了以下答案:https://stackoverflow.com/a/1350550/1305501

问题:如何使用vmsplice将内存页面从一个进程转移到另一个进程而不复制数据(即零拷贝)?

上述答案声称有可能。但是,它不包含任何源代码。如果我正确理解vmsplice的文档,如果内存被正确分配和对齐,以下函数将把内存页面转移到管道(内核缓冲区)而不复制。为了便于演示而省略了错误处理。

// data is aligned to page boundaries,
// and length is a multiple of the page size
void transfer_to_pipe(int pipe_out, char* data, size_t length)
{
    size_t offset = 0;
    while (offset < length) {
        struct iovec iov { data + offset, length - offset };
        offset += vmsplice(pipe_out, &iov, 1, SPLICE_F_GIFT);
    }
}

但是如何在不复制的情况下从用户空间访问内存页面?显然,以下方法不起作用:

  • vmsplice:此功能也可用于反向。但根据kernel sources中的评论,数据将被复制。
  • read:我可以想象,如果内存正确对齐,这个函数会有一些魔力,但我对此表示怀疑。
  • mmap:管道上不可能。但是有没有可以使用的虚拟文件,即splice虚拟文件的内存页面和mmap它?
  • ......?

vmsplice根本不可能吗?

1 个答案:

答案 0 :(得分:7)

如上所述,您只需将fd传递给接收进程somehow,另一方面将其用作普通fd。

编辑: 实际上,你必须在发送端使用vmsplice()将缓冲区映射到管道,并在管道另一端的接收端上拼接()。查看示例here

另一种选择是使用共享的mmap-ing。