问题描述
当由多个进程同时写入由mkfifo
创建的同一个命名管道时,我遇到了并发问题,其中有些写入丢失了。由于写进程的数量有限,我想从“从n个进程写到1个管道并从1个单独的读取”切换到“由n个进程写到n个管道并从1个单独的进程读取”。
目前,我正在通过read line <"$pipe"
循环读取,直到满足条件为止。 read
在此处阻止,直到读取一行为止。
我如何通过一个循环从多个管道($ pipe1,$ pipe2…$ pipeN)中读取直到满足条件,同时在所有管道上都使用相同的新行?
解决方法
一种解决最初描述的多个子写入单个FIFO问题的方法是让进程打开FIFO进行读取,但从不实际读取。除非FIFO已满,否则这将允许写程序进行写操作。我认为没有一个标准程序会一直持续睡眠直到发出信号。我使用自制程序pause
,这是一个非常小的C程序:
#include <unistd.h>
int main(void)
{
pause();
}
它直到发出信号才退出。在您的Shell脚本中,首先启动子项,告诉它们写入$FIFO
,然后运行:
pause <$FIFO &
pid=$!
请注意,直到重定向完成,类似pause
的命令才会在后台启动,并且直到有一个写入FIFO的进程,FIFO的打开才会完成-因此至少有一个在执行类似pause
的进程之前,需要在后台启动child。或编写pause
的变体(我叫我的sleepon
),以打开其参数列表中命名的文件-命令行类似于sleepon $FIFO &
,背景操作完成,{类似于{1}的程序将阻塞,直到它能够打开FIFO(这将在子进程中的一个打开FIFO进行写入时),然后无限期进入睡眠状态。但是pause
的代码比sleepon
的代码复杂得多。
一旦启动子进程和类似pause
的进程,父进程就可以继续主处理循环。
pause
主要要注意的是,每当FIFO清空时,父循环就会退出。您需要知道何时终止。在终止的时候,它将终止while read line
do
…
done < $FIFO
进程:pause
。您可能需要在行读取循环周围包裹一个kill $pid
循环-但是您可能需要一些更聪明的东西。这部分取决于您的“直到满足条件”的要求。
“从多个FIFO读取,所有FIFO可能间歇性地有数据”的要求并不容易做到。在C语言中并不是特别琐碎;我认为没有标准的(POSIX)shell命令可以帮助您解决此问题。在C语言中,您最终将使用POSIX select()
或
poll()
或它们的许多变体之一-其中一些是特定于平台的。可能会有特定于平台的命令会有所帮助;不过,我有疑问。