在不同的执行中保持FIFO可读

wbg*_*wbg 5 database linux pipe fifo

我之前从未使用过命名管道,最近意识到这正是我需要的.

我正在运行一个使用gnu parallel的程序,它可以生成为mySQL上的数据库格式化的输出吨(GB到1TB,现在很难知道).

我发现我可以打开两个终端:终端1有类似的东西:

find . -type f -name "*.h" | parallel --jobs 12 'cprogram {}' > /home/pipe
Run Code Online (Sandbox Code Playgroud)

管道是由fifo制成的mkfifo.

在第二个终端上,我运行一个类似于此的命令:

mysql DataBaseName -e "LOAD DATA LOCAL INFILE '/home/pipe' INTO TABLE tableName";
Run Code Online (Sandbox Code Playgroud)

有用...

但这很简陋......如果我理解正确,当第一个过程结束导致管道关闭时会产生EOF.

理想情况下,我想在具有不同参数的循环中运行第一个进程.每次迭代可能需要很长时间,我需要进行健全性检查,所以我不会放松一周,发现我有错误或错误的逻辑.

我想知道如何以标准方式将FIFO用于这种程序.

Fil*_*ves 3

如果我理解正确,当第一个进程结束导致管道关闭时会生成 EOF。

有点。还有更多的内容 - 从技术上讲,第一个进程结束后管道就会关闭,这在技术上是不正确的。

相反,当管道中没有更多数据并且没有任何进程打开管道进行写入时,管道和 FIFO 将返回 EOF。

通常,这是通过让读取进程打开 FIFO 进行读取和写入来解决的,即使它永远不会写入 - 例如,通过从 FIFO 读取来接受本地客户端的服务器可以打开 FIFO 进行读取和写入,因此当没有活动客户端时,服务器不必处理 EOF 的特殊情况。这是处理它的“标准”方法,如UNIX 环境中的高级编程中所述中有关 IPC 机制的章节中所述。

但就您而言,这实际上是不可能的,因为您没有持续运行的永久进程(也就是说,您没有相当于服务器进程的进程)。您基本上需要某种“持久写入器”,即在不同迭代期间保持管道打开以进行写入的进程。

我能想到的一种解决方案是cat在后台将标准输入发送到 FIFO。这确保cat打开 FIFO 进行写入,因此始终有一个活动写入器,但通过将其保留在后台,您实际上不会向其提供任何输入,并且它永远不会写入 FIFO。请注意,一旦cat尝试读取,该作业就会被 shell 停止(但不会终止) stdin(在后台进程组中运行的进程通常会发送 SIGTTIN,并在尝试读取时停止)stdin,因为它们不有一个控制终端,直到它们被带到前台)。不管怎样,只要你不给它任何输入,你就没事了——进程处于停止状态,但 FIFO 仍然打开用于写入。只要后台作业没有终止,您就永远不会在管道上看到 EOF。

所以,简而言之,你:

  1. 创建 FIFO:mkfifo /home/pipe
  2. 启动一个后台作业,打开 FIFO 进行写入:cat >/home/pipe &
  3. 按照您想要的方式运行您的程序,并按照您想要的迭代次数运行您的程序。忽略有关后台作业停止的 shell 消息。您可以就这样保留它,因为即使作业停止,管道仍然打开用于写入。
  4. 完成后,cat通过将后台带到前台并向其发送 SIGINT(通常是 Ctrl+C)或使用kill PID.

请注意,通过这样做,读取器进程(在本例中为 mysql)将永远不会知道输入何时结束。它总是会阻塞更多的输入,除非你在杀死mysql之前杀死后台cat