Bash 将命名管道与后台进程一起使用时的不同行为
我很难理解命名管道。我有以下脚本:Bash 将命名管道与后台进程一起使用时的不同行为,bash,background-process,named-pipes,Bash,Background Process,Named Pipes,我很难理解命名管道。我有以下脚本: #!/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
#!/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
和'b'),但没有任何效果。因此,我必须使用^C结束脚本
如果我在调用
a\u或后将回声重定向到管道:
...
mkfifo pipe
echo 'x' > pipe
a_or_b <pipe &
...
mkfifo pipe
a_or_b <pipe &
echo 'x' > pipe
这基本上就是我所期望的不向管道
回显任何内容的行为。函数开始,进入循环,从echo
(对应于输出中的两个0
s)读取x
和\n
字符,然后在无法读取任何字符的情况下永远保持循环。如果我将a
或b
回送到管道中,则函数结束
是什么导致了所有这些不同的行为
a_or_b <pipe &
不幸的是,这有着同样的问题,但却是相反的问题。在另一个进程打开FIFO进行读取之前,shell无法继续通过>管道
重定向。它永远不会到达回显
,也不会到达从管道读取的第二行
a_或b管道
希望您现在可以了解此版本的工作原理。背景shell尝试从管道和块中读取。前台shell是一个单独的进程,它向其中写入数据。啊哈!有两个进程打开了管道,一个用于读取,一个用于写入。他们现在都可以继续了。鸟儿在歌唱,每个人都很高兴。只要打开管道的读取端,而不是真正尝试读取,就会阻塞一个过程,直到另一端打开进行写入;mkfifo
手册页指出“[a FIFO]必须在两端同时打开,然后才能继续对其执行任何输入或输出操作。打开FIFO进行读取通常会阻塞,直到其他进程打开相同的FIFO进行写入,反之亦然。”为什么第一个函数调用然后回显到管道版本满足这个要求?为什么第一个回显到管道然后函数调用版本不是?我想我不明白你所说的“shell块试图打开管道进行读取”是什么意思,因为&
。工作的第一行在后台运行,因此它阻塞的事实不会阻止第二行运行。背景处理被阻塞了,没问题。如果你把<代码>和<代码>移到中间的第一行,它也会工作。
a_or_b <pipe &
echo 'x' > pipe
a_or_b <pipe &
a_or_b <pipe &
echo 'x' > pipe