2011-11-27 52 views
3

我的程序正在控制Linux上的外部应用程序,通过管道将输入命令传递到外部应用程序stdin,并通过外部应用程序stdout的管道读取输出结果。有没有办法将Linux管道设置为非缓冲或线路缓冲?

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

当我的外部应用程序设置为/斌/猫-n(它回显输入,添加了行号),它工作正常,现在看来,在每行后刷新。强制外部应用程序刷新的唯一方法是将退出命令给它;当它收到命令时,它会刷新,所有答案出现在stdout上,就在退出之前。

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

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

+0

这是另一个优秀的Linux缓冲讨论: http://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe – AAAfarmclub

回答

5

请勿使用管道。改用pty。如果您需要,Pty(伪ttys)具有线缓冲的优点,它为您的数据流提供了简单的帧。

0

为什么叫fflush适当(写入侧)不为你工作?

可以使用poll(或其他系统调用一样ppollpselectselect)检查读出侧输入的可用性。

如果外部应用程序使用,而不<stdio.h>适当调用fflush(可能由setbuf使它发生在换行符....),数据将保持其FILE*缓冲器内,甚至没有被发送(具有write系统调用)的管!

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

正如迈克尔狄龙建议,使用pty-s可能是最好的。但很难(我忘记了血淋淋的细节)。

+0

答案很简单:这不是我的计划。 (困难的答案:我们试图将Delphi的东西移植到Linux上;外部程序是一个Delphi运行的命令行util,我不确定Delphi的flush()是干什么的,它是否会工作。试试吧,但即使它的工作原理,这个问题值得解决的问题。) – ern0

+0

但如果应用程序没有冲洗,那么它是越野车来的是无法使用的地步... –

+0

应用在外壳的伟大工程。嗯,我现在有一个想法。 – ern0

1

默认情况下,标准输入和标准输出会被完全缓冲,除非它们连接到交互式设备,在这些交互设备中,它们是线路缓冲的[1]。管道是非交互式设备。 PTYs 交互式设备。 “完全缓冲”是指“使用一定大小的内存块”。

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

[1]详情请参阅“stdin(3)”和“setbuf(3)”。

2

使用PTY可能是对手头问题的矫枉过正(虽然它工作)。

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

大多数UNIX实现将调用isatty来决定是否做全缓冲或行缓冲对于一个给定的文件描述符。

嗯,glibc不。它要求__fxstat,然后只有当状态指示fd是要一个字符设备调用isatty。所以你需要介入__fxstatisatty。更多关于图书馆介入here

+0

下面是使用PTY http://rachid.koucha.free.fr/tech_corner/pty_pdip.html#Inter-process_communication_through_a一个很好的例子 – ern0