我是Linux内核的新手。最近,我已经通过了内核2.6.33中的sendfile syscall。以下是我的旅程序列:DMA复制在拼接()
do_sendfile()
=> do_splice_direct()
=> splice_direct_to_actor()
=> do_splice_to()
=> do_splice_from()
=> splice_read,splice_write
在整个序列中,我没有找到拼接使用DMA副本的地方。那么DMA复制发生在哪里?
我是Linux内核的新手。最近,我已经通过了内核2.6.33中的sendfile syscall。以下是我的旅程序列:DMA复制在拼接()
do_sendfile()
=> do_splice_direct()
=> splice_direct_to_actor()
=> do_splice_to()
=> do_splice_from()
=> splice_read,splice_write
在整个序列中,我没有找到拼接使用DMA副本的地方。那么DMA复制发生在哪里?
接合不做任何DMA副本。事实上,拼接的主要用途是避免复制 - 它试图将引用传递给内存页面,而不是复制缓冲区。
关于拼接提到的DMA将发生在“叶”处 - 这些拼接所经过的引用的起源将由例如磁盘控制器DMA创建到缓冲区中,并将由一个以太网控制器DMA的页面内容作为数据包的一部分 - 至少在一个“完美的”零拷贝的情况下,这是很难实现和罕见的。
Splice不执行DMA - 它不允许在第一个DMA和最后一个DMA之间进行复制。
据我所知splice_ *基础设施是最好的,以尽量减少实际复制的数量。读者最多只能从作者正在填写的同一组页面中阅读。
在LWN上有一些优秀的文章描述了splice()的各个位,包括新的系统调用。
嗨stsquad,谢谢你的回答。我会在那里看一看。 – sliter
嗨,感谢您的回答,这真的很有帮助。所以如果我正确地理解你说的话,拼接的顺序将是:从磁盘驱动器复制到fd_in缓冲区; fd_in缓冲区通过管道将页面引用传递给fd_out缓冲区;通过查看fd_out缓冲区中的引用,以太网卡直接进入fd_in缓冲区以查看实际数据。 – sliter
@sliter是的,这是主意。 – gby