21

目前,我正在尝试了解 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: 此功能也可用于反向。但根据内核源代码中的注释,数据将被复制。
  • read: 我可以想象,如果内存正确对齐,这个函数会产生一些魔力,但我对此表示怀疑。
  • mmap: 在管道上不可能。但是是否有某种虚拟文件可以代替使用,即splice虚拟文件的内存页和mmap它?
  • ... ?

根本不可能vmsplice吗?

4

1 回答 1

7

正如 R.. 所提到的,您只需要以某种方式将 fd 传递给接收进程,然后将其用作普通 fd。

编辑: 实际上,您必须在发送端使用 vmsplice() 将缓冲区映射到管道,并在管道另一端的接收端使用 splice()。请参阅此处的示例。

另一种选择是使用共享映射。

于 2012-05-17T16:46:38.160 回答