当从 fifo 重定向输入时,为什么 stdout 不会刷新?

当从 fifo 重定向输入时,为什么 stdout 不会刷新?

我有一个程序显示提示消息并等待用户输入一些文本。

$ 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 时显然没有使用。

解决方案:

  1. cat fifo | program

    cat从 FIFO 读取直到文件结尾,然后退出。

  2. tail -f fifo | program

    tail从 FIFO 读取直到文件结束,然后挂起等待更多内容直到终止。

其中哪一个最适合您的情况在一定程度上取决于另一端写入 FIFO 的内容以及写入方式。

第三种解决方案是让程序在需要时打开 FIFO。


根据基本原理部分sh,shell 必须将标准输入设置为阻塞,因为......

如果 shell 没有重置此标志,它将立即终止,因为还没有可用的输入数据,这将被视为与文件结束相同。

相关内容