从命名管道读取unix fifo并使其中一个进程未终止

时间:2018-02-20 05:58:32

标签: unix concurrency fifo solaris-10 mkfifo

我在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会进行大量活动。

请帮助我了解知识

1 个答案:

答案 0 :(得分:1)

  

我已经引入了睡眠2以避免发生竞争状况

首先,这不会起作用。 sleep未明确同步任何内容。

其次,除非每个阅读过程知道一次尝试阅读多少,否则不能从管道“共享”阅读。 read脚本中的sh无法控制sh二进制文件实际从具有低级别read()调用的管道读取的字节数它用。 sh进程可能会尝试读取PIPE_BUF个字节,但它可以尝试读取任何内容,因为它实际上只是提供了一个流。你无法控制它的读取量。

例如,每个进程需要知道管道的下一次读取需要是143个字节,然后它会发出一个低级read( fd, buffer, 143 );调用来读取 143个字节

即使您可以控制每个进程读取的最低级别,每个进程都需要知道要读取多少,在这种情况下您无法知道。

拥有预先知道的读取大小对于执行您想要的操作是必要的,并且在使用脚本时您没有这样做。但请注意,它可能还不够 - 即使您解决了共享阅读器问题,您也可能会遇到尝试共享阅读器的其他问题。

在这种情况下几乎可以肯定的是,您运行的第一个脚本会消耗传递到管道中的所有数据,然后在没有更多数据时关闭并继续运行。 THEN 第二个脚本打开管道并等待数据 - 但是没有,所以它只是阻塞。