【问题标题】:Linux Zero-Copy: Transfer memory pages between two processes with vmspliceLinux 零拷贝:使用 vmsplice 在两个进程之间传输内存页面
【发布时间】:2012-05-25 06:09:19
【问题描述】:

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

vmsplice 根本不可能吗?

【问题讨论】:

  • 我认为创建一个名为“send()”的非静态函数不是一个好主意。
  • 确实,这是在 POSIX 上调用未定义的行为。
  • 我认为您在receive 中对vmsplice 的调用没有意义。这是一个写作的呼吁,而不是阅读......
  • 虽然我系统的手册页中没有提到,vmsplice 显然支持两个方向。但是,正如我所指出的,相反的方向不是零拷贝。请参阅source of vmsplice

标签: c linux virtual-memory splice


【解决方案1】:

正如 R.. 所提到的,您只需将 fd 传递给接收进程 somehow 并在另一端将其用作普通 fd。

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

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

【讨论】:

  • 让我们假设另一个进程已经有一个 fd 到管道的另一端。问题是:它能否在不复制数据的情况下将内存页面映射到其地址空间?我怀疑read(2) 包含这样的优化,是吗?
猜你喜欢
  • 1970-01-01
  • 2011-07-05
  • 2019-02-21
  • 1970-01-01
  • 2019-08-22
  • 2012-04-22
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多