混淆 dup2()、exec() 和管道

Confusion with dup2(), exec() and pipes

我一直在努力理解涉及命令 dup2()exec() 和管道的概念。

我想要实现的目标:

Pipe the output of a program X to the input of a program Y.

一些基本的东西,比如 who | sort

with a parent and 2 children, where the children are responsible for executing the programs and the parent passing the programs to the children.

以下是我对管道不理解的地方:

P1) 管道被视为文件并且应该是单向的,但是是什么阻止我将一个管道用于多个单向通信通道? 因此,假设我有 pipe1 和三个具有管道的进程(P - parent - C1C2、children)通过分叉打开。所有这些进程都可以使用文件描述符。 假设我们做的一切都正确,关闭未使用的管道末端,P 现在向 C1 写入一些内容。 再次使用管道在 C1C2 之间进行通信有什么问题? 就在写这个问题的时候,一个想法打动了我:当许多进程可能同时打开它(两个进程正在阻塞以获取读取)时,谁从中读取它是否存在问题,即系统无法确定谁想要读取写入其中的缓冲数据?如果是这样,这在系统中是如何实现的?

我真的很想理解这个概念,所以请多多包涵。

为了将这个问题应用到现实生活中,我正在处理一些伪代码:

P:

C1:

C2:


现在,如果我按照上面的描述去做,我就没有运气了。 但是,如果我引入另一个管道 pipe2 它看起来像这样:
P:

C1:

C2:

管道不应在多个进程中重复使用的假设是否正确,因为系统可能不确定要向谁"serve"?或者还有其他原因吗?

管道主要是为一对一的交流而设计的——一位作者,一位 reader。虽然没有什么可以阻止您拥有尽可能多的 readers 和 writer,但这种行为通常使它不太有用,尤其是对于多个 readers:

  • 从管道读取是一种破坏性操作:通过管道发送的每个字节都将恰好被 reader 中的一个读取,无论谁先获取它。如果你想广播一些信息,你需要使用不同的 IPC 机制或显式复制数据(如 tee 命令)。
  • 如果有多个写入者,他们的写入会以某种不可预测的方式穿插。唯一的保证是大小 PIPE_BUF 或更小的写入是原子的。
  • 如果写入者数量降为零,reader 会看到文件结束条件。

在您所描述的体系结构中,您有两个独立的通信通道:P 将 who 发送到 C1,C1 将 运行 的输出 who 命令发送到 C2 .在 shell 脚本中,这类似于

echo who | { read command; exec command; } | sort

with echo who 在原始进程中执行而不是在子进程中执行shell。

你的第一个提议不可行,因为没有办法说 P 的输出将转到 C1,而 C1 的输出将转到 C2。它仍然是同一个管道,因此 P 的输出可以转到 C2,而 C1 的输出可以返回到它自己,也可以是混合。