从一个进程并行读取n个管道

问题描述

当由多个进程同时写入由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()或它们的许多变体之一-其中一些是特定于平台的。可能会有特定于平台的命令会有所帮助;不过,我有疑问。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...