【问题标题】:Read from n pipes from one process in parallel从一个进程中并行读取 n 个管道
【发布时间】:2021-02-20 17:12:21
【问题描述】:

当多个进程同时写入使用mkfifo 创建的同一个命名管道时,我遇到了并发问题,其中一些写入丢失了。由于写入进程的数量有限,我想从“从 n 个进程写入 1 个管道并从 1 个单独的读取”切换为“由 n 个进程写入 n 个管道并从 1 个单独的进程读取”。

目前我正在循环中通过read line <"$pipe" 阅读,直到满足条件。 read 在这里阻塞,直到读取一行。

如何通过一个循环从多个管道($pipe1、$pipe2 ... $pipeN)读取直到满足条件,同时尊重所有管道上新写入的行?

【问题讨论】:

  • 您使用的符号read line < "$pipe" 在每次迭代时打开和关闭管道。当(唯一的)阅读器关闭管道时,所有内容都会丢失 - 这就是您丢失消息的原因。您需要更像while read line; do … done < "$pipe" 的东西,它可以让管道保持打开状态,直到最后一个作者关闭它。使用命名管道很棘手。不管你是否使用命名管道,read 命令上的 I/O 重定向通常是错误的——除非你真的确定你只需要一个输入。
  • 我认为这可能是How to avoid echo closing FIFO named pipes — Funny behaviour of Unix FIFOs? 的副本,我认为问题的多个管道部分更多的是XY Problem,而不是您需要的。如果您确实需要从多个管道中读取数据,则需要一个 C 程序 — 使用 select()poll() 或类似的东西来查找哪些管道实际上有数据要读取。
  • 感谢您对最初问题的解释。事实上,这是一个 XY 问题。遗憾的是,您的提示并没有真正奏效。我针对最初的问题发布了question,并包含了切换到您的建议的结果。无论如何——即使它不能解决我最初的问题——我真的很想知道 this 帖子中描述的问题是否有解决方案?
  • 请提供minimal reproducible example;不太清楚你在问什么。

标签: bash concurrency named-pipes mkfifo


【解决方案1】:

处理最初描述的多个子级写入单个 FIFO 的问题的一种方法是让一个进程打开 FIFO 进行读取,但从不实际读取它。这将允许写入器写入,除非 FIFO 已满。我不认为有一个标准程序会永远进入休眠状态,直到发出信号。我使用了一个自制程序pause,这是一个非常小的 C 程序:

#include <unistd.h>

int main(void)
{
    pause();
}

在发出信号之前它永远不会退出。在你的 shell 脚本中,首先启动孩子,告诉他们写信给$FIFO,然后运行:

pause <$FIFO &
pid=$!

注意pause-like 命令在重定向完成之前不会被启动到后台,并且 FIFO 的打开在有写入 FIFO 的进程之前不会完成——所以至少需要一个子进程在执行pause-like 进程之前在后台启动。或者编写pause 的变体(我叫我的sleepon),它打开在其参数列表中命名的文件——然后命令行类似于sleepon $FIFO &amp;,后台操作完成,pause-like 程序块直到它能够打开 FIFO(这将是当其中一个孩子打开 FIFO 进行写入时),然后无限期地进入睡眠状态。但是sleepon 的代码比pause 的代码复杂得多。

一旦子进程和pause-like 进程启动,父进程就可以继续主处理循环。

while read line
do
    …
done < $FIFO

主要需要注意的是,只要 FIFO 被清空,父循环就会退出。您需要知道它应该何时终止(如果有的话)。在它终止的地方,它应该终止pause 进程:kill $pid。您可能需要在行阅读循环周围包裹一个while true; do … done 循环——但您可能需要比这更聪明的东西。这部分取决于您的“直到满足条件”的要求是什么。

“从多个 FIFO 中读取,所有这些 FIFO 上可能会间歇性地包含数据”的要求并不容易实现。这在 C 中并不是特别简单;我认为没有标准的(POSIX)shell 命令可以帮助解决这个问题。在 C 语言中,您最终会使用 POSIX select()poll() 或其众多变体之一——其中一些是特定于平台的。可能有一个特定于平台的命令会有所帮助;不过,我有疑问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    相关资源
    最近更新 更多