有没有办法将Linux管道设置为非缓冲或行缓冲?

时间:2011-11-27 17:08:32

标签: c linux pipe flush

我的程序在Linux上控制外部应用程序,通过管道将输入命令传递到外部应用程序stdin,并通过外部应用程序标准输出管道读取输出结果。

问题是对管道的写入是按块而不是按行缓冲的,因此在我的应用程序接收外部应用程序输出数据之前会发生延迟。无法更改外部应用程序以添加显式fflush()调用。

当我将外部应用程序设置为 / bin / cat -n (它回显输入,添加了行号)时,它可以正常工作,似乎 cat 每行后冲洗。强制外部应用程序刷新的唯一方法是向其发送 exit 命令;当它收到命令时,它会刷新,所有答案都会在退出之前显示在标准输出上。

我很确定,Unix管道对于那种进程间通信(伪服务器 - 客户端)来说是合适的解决方案,但也许我错了。

(我刚刚复制了一些类似问题的文字:Force another program's standard output to be unbuffered using Python

4 个答案:

答案 0 :(得分:5)

不要使用烟斗。请改用pty。 Pty(伪ttys)具有线缓冲的好处,如果你需要它,它可以为你的数据流提供简单的框架。

答案 1 :(得分:2)

使用PTY可能对手头的问题有些过分(尽管工作)。

如果“目标应用程序”(Delphi命令行实用程序)是动态链接的,则可能更简单的解决方案是将(通过LD_PRELOAD)小型库插入应用程序。该库只需要实现isatty,并回答true(返回1),无论输出是输入管道还是终端。您可能希望对所有文件描述符执行此操作,或仅针对STDOUT_FILENO

大多数UNIX实现都会调用isatty来决定是否对给定的文件描述符执行完全缓冲或行缓冲。

嗯,glibc没有。如果状态指示__fxstat将转到字符设备,则会调用isatty,然后仅调用fd。因此,您需要设置__fxstatisatty。有关库插入here的更多信息。

答案 2 :(得分:1)

默认情况下,标准输入和标准输出是完全缓冲的,除非它们连接到交互式设备,在这种情况下它们是行缓冲的[1]。管道是非交互设备。 PTY 交互式设备。 “完全缓冲”意味着“使用一定大小的内存”。

我确定你想要线缓冲。因此,使用主/从PTY而不是管道应该使受控应用程序自动进入正确的缓冲模式。

[1]详见“stdin(3)”和“setbuf(3)”。

答案 3 :(得分:0)

为什么适当地调用fflush(在写入方面)不适合你?

您可以使用poll(或其他系统调用,例如ppollpselectselect)来检查阅读方面的输入可用性。

如果外部应用程序正在使用<stdio.h>而没有恰当地调用fflush(可能是setbuf使其在新行上发生....),数据将保留在其FILE*内缓冲区甚至没有被发送(使用write系统调用)到管道!

应用程序可以检测其输出是否是具有例如终端的终端。 isatty。但它应该确保冲洗发生......

正如Michael Dillon建议的那样,使用pty - s可能是最好的。但这很难(我忘了血淋淋的细节)。