【问题标题】:C streams: Copy data from one stream to another directly, without using a bufferC 流:直接将数据从一个流复制到另一个流,不使用缓冲区
【发布时间】:2014-01-27 16:31:36
【问题描述】:

我想将数据从一个流复制到另一个。现在通常,我会这样做:

n = fread(buffer, 1, bufsize, fin);
fwrite(buffer, 1, n, fout);

有没有办法直接将数据从fin写入fout,不经过缓冲区,即代替fin->buffer->fout,我想直接做fin->fout(无缓冲区)。

在 ANSI C 中可以这样做吗?如果没有,是否可以使用 POSIX 函数来实现?还是特定于 Linux 的解决方案?

【问题讨论】:

  • 我不这么认为,因为 AFAIK freopen() 只能破坏输入或输出流,但似乎无法将输入连接到输出。
  • 它是 Linux 并且 /output 实际上是一个命名管道 - 但我不知道如何解决问题。
  • 某个进程将数据写入我程序的标准输入。我的程序的工作是建立一个命名管道并将该数据放入命名管道。
  • “某个进程”不知道命名管道的名字,我的程序的工作就是找一个空闲的名字,设置管道等等。
  • 事实上我的程序做的不止这些——它还决定是使用管道还是使用另一个接口。这当然不是多余的;-)

标签: c linux stream posix


【解决方案1】:

两种可能的仅限 Linux 的解决方案是 splice()sendfile()。他们所做的是在不离开内核空间的情况下复制数据,从而进行潜在的显着性能优化。

请注意,两者都有限制

  • sendfile()在2.6.33之前的Linux内核需要一个socket作为输出,之后任何文件都可以作为输出,还需要输入支持mmap()操作,也就是说输入可以'不是stdin 或管道。

  • splice() 要求输入或输出流之一是管道(不确定两者),并且对于内核版本 2.6.30.10 和更早版本,它需要不是流的文件系统支持拼接的管道。

编辑:注意some filesystems might not support splicing for Linux 2.6.30.10 and below

【讨论】:

  • sendfile() 听起来很有希望,但我总是得到 EINVAL,可能是因为根据手册页:“in_fd 无法使用类似 mmap(2) 的操作”——这对于标准输入来说是合理的。
  • splice() 适用于我的桌面(Linux 3.11),但不适用于我的实际目标系统,可能是因为 vhost-limitations(也得到 EINVAL,可能是因为根据手册页:“目标文件系统不支持拼接”。
  • 我会接受你的回答,但你应该从中删除 sendfile()。
  • 好吧,我的便宜的虚拟主机 Linux 2.6 对 splice() 来说不够好......不过非常感谢您的支持。
猜你喜欢
  • 1970-01-01
  • 2011-04-13
  • 2017-05-27
  • 2019-09-27
  • 2010-09-18
  • 2011-06-22
  • 1970-01-01
  • 2013-02-21
相关资源
最近更新 更多