我有一个程序显示提示消息并等待用户输入一些文本。
$ program
Input a line of text: <aaaa>
Some more output.
$
现在,我还希望能够通过 FIFO 以编程方式提供此输入,如下所示:
$ program < fifo
但发生的情况是,直到我将输入提供给 .stdout 时才会出现提示fifo
。
接下来我尝试了一个与我的程序非常简单的等效项,如下所示:
$ echo aaaa < fifo
即使在这里,在提供输入aaaa
之前也不会出现。fifo
问题:使用 FIFO 时,如何使输出直到等待输入stdin
出现为止?stdout
答案1
FIFO 由 shell 打开,但它的打开是阻塞的,直到 FIFO 被其他进程打开进行写入为止。由于处理了重定向前命令执行后,程序甚至不会执行,直到 shell 的open()
调用返回。这是有记录的行为Copen()
库函数(由外壳使用):
O_NONBLOCK
O_RDONLY
当使用或设置打开 FIFO 时O_WRONLY
:
如果
O_NONBLOCK
设置,则open()
只读将立即返回。open()
如果当前没有进程打开该文件进行读取,则只写将返回错误。如果
O_NONBLOCK
清楚的话,一个open()
只读 应阻塞调用线程,直到线程打开文件进行写入。只open()
写应阻塞调用线程,直到线程打开文件进行读取。
所以 shellO_NONBLOCK
在打开 FIFO 时显然没有使用。
解决方案:
cat fifo | program
cat
从 FIFO 读取直到文件结尾,然后退出。tail -f fifo | program
tail
从 FIFO 读取直到文件结束,然后挂起等待更多内容直到终止。
其中哪一个最适合您的情况在一定程度上取决于另一端写入 FIFO 的内容以及写入方式。
第三种解决方案是让程序在需要时打开 FIFO。
根据基本原理部分sh
,shell 必须将标准输入设置为阻塞,因为......
如果 shell 没有重置此标志,它将立即终止,因为还没有可用的输入数据,这将被视为与文件结束相同。