我在solaris中创建了一个名为fifo的管道,它将文件的内容逐行写入管道,如下所示:
$ mkfifo namepipe
$ cat books.txt
"how to write unix code"
"how to write oracle code"
$ cat books.txt >> namepipe &
我有一个 readpipe.sh
脚本,它会像这样并行读取命名管道:
# readpipe.sh
while IFS=',' read var
do
echo var >> log.txt
done < namepipe
我打电话给readpipe.sh
喜欢
readpipe.sh &
sleep 2
readpipe.sh &
我引入了sleep 2
以避免出现竞争条件,即两个进程从每一行获取值的一部分,如进程1获取
“如何”
和进程2获取
“编写unix代码”
我面临的问题是当namepipe
的所有内容都完成后,第一个后台进程退出,而第二个进程继续运行而没有完成。
为了清楚理解,脚本中的逻辑在此处被声明为简单。实际readpipd.sh
会进行大量活动。
请帮助我了解知识
答案 0 :(得分:1)
我已经引入了睡眠2以避免发生竞争状况
首先,这不会起作用。 sleep
未明确同步任何内容。
其次,除非每个阅读过程知道一次尝试阅读多少,否则不能从管道“共享”阅读。 read
脚本中的sh
无法控制sh
二进制文件实际从具有低级别read()
调用的管道读取的字节数它用。 sh
进程可能会尝试读取PIPE_BUF
个字节,但它可以尝试读取任何内容,因为它实际上只是提供了一个流。你无法控制它的读取量。
例如,每个进程需要知道管道的下一次读取需要是143个字节,然后它会发出一个低级read( fd, buffer, 143 );
调用来读取仅 143个字节
即使您可以控制每个进程读取的最低级别,每个进程都需要知道要读取多少,在这种情况下您无法知道。
拥有预先知道的读取大小对于执行您想要的操作是必要的,并且在使用脚本时您没有这样做。但请注意,它可能还不够 - 即使您解决了共享阅读器问题,您也可能会遇到尝试共享阅读器的其他问题。
在这种情况下几乎可以肯定的是,您运行的第一个脚本会消耗传递到管道中的所有数据,然后在没有更多数据时关闭并继续运行。 THEN 第二个脚本打开管道并等待数据 - 但是没有,所以它只是阻塞。