【问题标题】:linux pipe data from file descriptor into a fifolinux管道数据从文件描述符到fifo
【发布时间】:2016-02-21 13:19:29
【问题描述】:

假设我知道文件描述符fd 已打开以供在我的进程中读取。我想将来自这个fd 的数据通过管道传输到一个fifo 中,该fifo 可以在我的进程之外读取,以避免在fd 上调用pollselect 并手动读取/转发数据。这个可以吗?

【问题讨论】:

    标签: linux shell pipe system-calls file-descriptor


    【解决方案1】:

    您的意思是要求操作系统从现在开始持续在幕后执行此操作?像 I/O 重定向?

    不,你不能那样做。

    不过,您可以生成一个除了读取文件 fd 并写入管道 fd 之外什么都不做的线程。为了避免在read(2)write(2) 系统调用中复制内存的开销,您可以使用sendfile(out_fd, in_fd, NULL, 4096) 告诉内核将页面从in_fd 复制到out_fd。见the man page

    with splice(2) 可能会有更好的结果,因为它是为文件和管道设计的。 sendfile(2) 曾经要求 out_fd 是一个套接字。 (设计用于在 TCP 套接字上发送静态数据的零拷贝,例如来自 Web 服务器。)


    Linux 确实有asynchronous I/O,因此您可以排队读取或写入以在后台发生。这不是一个好的选择,因为您不能将副本从一个 fd 排队到另一个。 (没有异步 splice(2)sendfile(2))。即使有,它也会有一个特定的请求大小,而不是一劳永逸的复制。 AFAIK,线程已成为执行异步 I/O 的首选方式,而不是 POSIX AIO 工具。

    【讨论】:

    • 感谢您的解释,我猜splice 在单独的线程中是一个不错的选择。 sendfile 对它可以发送的字节数有限制。
    • @iggy: splice 和 sendfile 都有一个 size_t 长度参数。 IDK 如果最好用像 64kiB 这样的小尺寸来调用它们,或者如果使用 SIZE_MAX 比较好,那么您的用户空间循环仅在系统调用被中断时发生(例如,通过信号)。实际上传输 2^64-1 字节不太可能至少可以说,但你不应该假设调用永远不会返回。
    • 为 sendfile sendfile() will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred. (This is true on both 32-bit and 64-bit systems.) 引用文档,但感谢您提出拼接建议,这肯定会起作用
    • @iggy:你在哪个文档中找到的?它不在当前手册页中(Linux 手册页 3.74,sendfile 手册页上次编辑时间为 2011-09-14)。如果它是一个旧的限制已被删除,或者文档以前不完整,那么 IDK。
    • 你是对的,这可能不是最新的资源man7.org/linux/man-pages/man2/sendfile.2.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    相关资源
    最近更新 更多