【问题标题】:Doing a zero-copy move of data from a Linux kernel buffer to hard disk将数据从 Linux 内核缓冲区零拷贝移动到硬盘
【发布时间】:2010-09-20 19:19:54
【问题描述】:

我正在尝试将数据从内核空间中的缓冲区移动到硬盘中 磁盘,而不必从内核缓冲区产生任何额外的副本到 用户缓冲区或任何其他内核缓冲区。任何想法/建议都是 最有帮助。

用例基本上是一个 demux 驱动程序,它将数据收集到一个 内核空间中的 demux 缓冲区,并且该缓冲区必须被清空 定期将内容复制到基于 FUSE 的分区中 磁盘。当缓冲区变满时,会向用户进程发出信号,然后 确定磁盘上的扇区号 需要复制的内容 到。

我希望将上面的 demux 内核缓冲区映射到用户地址 空间并向原始分区设备发出写入系统调用。但 从我所看到的,这个数据被内核缓存在它的 硬盘驱动程序的方法。所以我假设这涉及 linux 内核的额外副本。

此时我想知道是否还有其他机制可以做到这一点 不涉及内核的额外副本。我意识到这是一个 非嵌入式环境的不寻常使用场景,但我会 感谢您对可能的选项的任何反馈。

顺便说一句 - 我在打开原始分区时尝试使用 O_DIRECT,但是 如果传递的缓冲区是 映射缓冲区。

谢谢!

【问题讨论】:

  • 也许你可以用一对 splice() 做点什么。

标签: linux-kernel


【解决方案1】:

您需要将 demux 缓冲区公开为文件描述符(大概,如果您使用的是 mmap(),那么您已经在这样做了 - 太好了!)。

在内核端,您需要实现struct file_operationssplice_read 成员。

在用户空间端,创建pipe(),然后使用splice() 两次——一次将数据从demux 文件描述符移动到管道,第二次将数据从管道移动到磁盘文件.使用SPLICE_F_MOVE 标志。

正如splice() 手册页中所述,它将通过复制对内核内存页面的引用而不是页面本身来避免实际的副本。

【讨论】:

  • SPLICE_F_MOVE 在最新的内核代码中没有任何操作.. 2.6.31 以后。所以,我不确定拼接实现是否真的尝试进行零拷贝传输。你能确认一下吗?
  • 我尝试进行一些测试,但在设备驱动程序中找不到任何 splice_read() 和 splice_write() 的示例实现。似乎还没有人开始使用 splice() 。你有 splice_read() 的参考资料吗?
  • 您可能希望在 fs/splice.c 中查看默认的拼接实现。 lxr.linux.no/#linux+v3.2.7/fs/splice.c#L584
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-16
  • 1970-01-01
  • 2017-09-22
  • 2013-08-22
  • 2023-03-31
  • 2011-12-18
  • 1970-01-01
相关资源
最近更新 更多