使用命名管道的 bash IPC

使用命名管道的 bash IPC

考虑下面的脚本

#!/usr/bin/bash

chan=/tmp/pipe.$$
mkfifo $chan
{
    for x in a b c d e
    do
        echo $x > $chan
    done
} &
for y in 1 2 3 4 5
do
    x=$(cat $chan)
    echo "var $x = $y ;"
done
rm $chan

似乎没有按预期工作。例如

❯ ./testpipe.sh
var a
b
c = 1 ;
^C

如果 fifo 没有读者,那么 echo 是否不应该等待?当我在终端中执行此操作时,它会按预期挂起

❯ mkfifo /tmp/pipe
❯ echo 1 > /tmp/pipe
^C

为什么它在脚本中的表现不同?


更新

我改为使用fds,而不是每次都打开。

#!/usr/bin/bash
chan=/tmp/pipe.$$
mkfifo $chan    
{
    exec 5>"$chan"
    for x in a "ba ba ba baanannna" c d e
    do
        echo $x >&5
    done
} &

exec 6<"$chan"
for y in 1 2 3 4 5
do
    read -u 6 x
    echo "var $x = $y ;"
done
rm $chan

不确定我修复了它还是只是让比赛变得更加罕见。

❯ ./testpipe.sh
var a = 1 ;
var ba ba ba baanannna = 2 ;
var c = 3 ;
var d = 4 ;
var e = 5 ;

更新2

根本不需要fifo。只需 proc 替换就足以在后台运行某些内容并在需要时从中读取。测试了在生产者和消费者中添加睡眠之前和之后。似乎工作正常。可能没有比赛。

#!/usr/bin/bash

produce()
{
    for x in a "ba ba ba   baanannna" "more    space" d e
    do
        echo "$x"
    done
}

exec {fd}< <(produce)
for y in 1 2 3 4 5
do
    read -u $fd x
    echo "var $x = $y ;"
done

答案1

Running in background shell -- running in foreground shell

echo a waits
                        cat opens read side
                        cat is maybe faulting in some pages or maybe not just picked 
                        but for whatever reason doesn't immediately call read
echo a completes
echo b doesn't wait (read side already open) and completes
echo c ditto
                        cat calls read, gets a NL b NL c NL and writes them 
                        (but the shell's $(...) that reads them drops the final NL)
echo d probably doesn't wait, but might if cat has close'd already (race condition)

如果你成功了$(cat <$chan),你可能会得到所有 ae,因为那时子外壳在读取之前执行 cat 之前打开读取端,增加延迟。 OTOH 如果您使用command echo/bin/echo来减慢生产者的速度,您可能只会得到一个。

相关内容