【发布时间】: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