我很难理解命名管道。我有以下脚本:
#!/bin/bash
function a_or_b {
echo 'func begins'
while true; do
echo 'loop begins'
read -s -n 1; echo $?
case $REPLY in
'a') return 0 ;;
'b') return 1 ;;
esac
done
echo 'func ends'
}
mkfifo pipe
a_or_b <pipe &
现在我期望此脚本执行的操作是:
a_or_b
,然后打印func begin
loop begins
pipe
中读取(因为我还没有写任何东西到pipe
),因此打印{{ 1}}作为1
运行此脚本时,尽管没有任何输出,并且终端仅显示其下一个提示。
如果我将 echo 重定向到$?
,然后呼叫pipe
:
a_or_b
...该脚本不会停止运行,我可以继续在终端中输入字符(包括...
mkfifo pipe
echo 'x' > pipe
a_or_b <pipe &
和'b'),但无效。所以我必须使用 ^ C 结束脚本。
如果我在调用a
之后将 echo 重定向到pipe
:
a_or_b
...我得到以下输出:
...
mkfifo pipe
a_or_b <pipe &
echo 'x' > pipe
这基本上是我期望的不从任何东西回波到func begins
loop begins
0
loop begins
0
loop begins
1
loop begins
1
loop begins
1
的行为。函数开始,进入循环,从pipe
读取x
和\n
字符(对应于输出中的两个echo
),然后一直循环而无法读取任何字符。而且,如果我在管道中 0
或a
回显,则函数结束。
是什么原因导致所有这些不同的行为?
答案 0 :(得分:3)
a_or_b <pipe &
在启动命令之前先处理重定向。外壳程序阻止尝试打开pipe
进行读取。来自mkfifo(3) man page:
打开FIFO以正常读取块,直到其他进程打开相同的FIFO进行写入为止,反之亦然。
只有在另一个进程打开FIFO进行写入之后,shell才能继续进行。只有这样,它才能完成重定向的设置并实际调用a_or_b
。
echo 'x' > pipe
a_or_b <pipe &
不幸的是,这具有相同但相反的问题。在另一个进程打开FIFO进行读取之前,shell无法继续通过> pipe
重定向。它永远不会到达echo
或从管道读取的第二行。
a_or_b <pipe &
echo 'x' > pipe
希望您现在可以看到此版本为何起作用。后台外壳程序尝试从管道和块中读取。前景外壳程序是一个独立的进程,会对其进行写入。啊哈!有两个过程打开了管道,一个过程用于读取,一个过程用于写入。他们现在都可以继续进行。鸟儿唱歌,每个人都很开心。