c - Linux 内核 splice() 是零拷贝吗?

标签 c linux linux-kernel

我知道 splice() 是为零复制而设计的,并使用 Linux 内核管道缓冲区来实现这一点。例如,如果我想将数据从一个文件描述符 (fp1) 复制到另一个文件描述符 (fp2),则不需要从“内核空间->用户空间->内核空间”复制数据。相反,它只是在内核空间中复制数据,流程就像“fp1 -> pipe_read -> pipe_write -> fp2”。 我的问题是剂量内核需要在“fp1 -> pipe_read”和“pipe_write -> fp2”之间复制数据吗?

维基百科是这样说的:

Ideally, splice and vmsplice work by remapping pages and do not actually copy any data,    
which may improve I/O performance. As linear addresses do not necessarily correspond to
contiguous physical addresses, this may not be possible in all cases and on all hardware 
combinations.

我已经追踪到kernel source(3.12)对于我的问题,我发现“fp1->write_pipe”之间的流程最终会在 fs/splice.c 中调用 kernel_readv()然后调用“do_readv_writev()”,最后调用“aio_write()”

558 static ssize_t kernel_readv(struct file *file, const struct iovec *vec,
559                 unsigned long vlen, loff_t offset)
//*vec would point to struct page which belong to pipe

“read_pipe -> fp2”之间的流程最后会调用“__kernel_write()”,然后调用“fp2->f_op->write()”

430 ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
//*buf is the pipe buffer

而且我认为“aio_write()”和“file->f_op_write()”都会执行真正的数据复制,那么 splice() 真的执行零复制吗?

最佳答案

据我了解,splice() 会读取 fd1 的页面,MMU 会映射这些页面。映射创建的引用将被放入管道并交给fd2。 在此过程中不应复制真实数据,只要每个参与者都有可用的 DMA。 如果没有可用的 DMA,则需要复制数据。

关于c - Linux 内核 splice() 是零拷贝吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21035237/

相关文章:

linux - exec 不替换当前进程,posix_spawn 内核实现

memory-management - alloc_pages() 和 get_free_pages() 返回值的区别

c - 用c语言在localhost上传adobe reader文件

c - 当我在 select 中使用 read() 时我有一个问题

linux - 如何在启动 Linux 的纯命令行界面后打开应用程序?

linux - Bash 生成正数和负数之间的随机数

c - 在 C 中通过 TCP (SOCK_STREAM) 套接字传递结构

c - 此 C 代码如何在执行时产生堆栈溢出?执行步骤是什么?

linux - 为什么 pthread_setschedparam() 在 opensuse 11.4 上生成 EPERM

linux - 通过评估 CPU 寄存器找出系统锁定时正在执行哪个 Linux 进程