我可以通过管道将任意两个进程相互连接吗?

我可以通过管道将任意两个进程相互连接吗?

这一页4.4BSD操作系统的设计与实现,据说:

管道和套接字之间的主要区别在于管道需要公共父进程来建立通信通道

但是,如果我记录正确,创建新进程的唯一方法就是创建fork现有进程。所以我真的不明白两个进程怎么可能没有共同的祖先。那么我认为任何一对进程都可以通过管道相互连接是否正确?

答案1

那么我认为任何一对进程都可以通过管道相互连接是否正确?

并不真地。

管道需要由父进程设置一个或多个孩子是分叉的。一旦子进程被分叉,它的文件描述符就不能“从外部”操作(忽略调试器之类的东西),父进程(或任何其他进程)不能在事后执行“设置 comms.channel”部分。

因此,如果您采用两个已经在运行的随机进程,则无法直接在它们之间设置管道。您需要使用某种形式的套接字(或其他 IPC 机制)来让它们进行通信。 (但请注意,某些操作系统(其中包括 FreeBSD)允许您在 Unix 域套接字上发送文件描述符。)

答案2

这句话不是很清楚。第一的,家长应该祖先,因为设置管道的进程可以是父进程,或祖父母,或曾祖父......祖父母,或通信进程之一。其次,这句话的意思并不是“如果你想要一个管道,就必须存在一个共同的祖先进程”,而是“如果你想要一个管道,就必须有一个共同的祖先进程来设置它”。

在底层,一个进程与自身建立了一个管道。管道是一个像其他文件描述符一样的文件描述符,或者更准确地说是一对文件描述符,每一端一个。创建管道的进程可以立即使用它向自身发送数据,尽管这很少有用(尽管自管确实有它的用处)。

一种典型的习惯用法是进程建立一个管道,然后分叉一个子进程,并在父进程中关闭管道的一端,在子进程中关闭管道的另一端。这使得父进程和子进程可以在一个方向上进行通信。如果进程需要双向通信,则它们需要两个管道(除了某些 UNIX 变体中管道是双向的)。

管道由任何子进程依次继承,因此创建管道的进程可能不参与通信。例如,在两个外部命令之间创建的 shell 中的管道ls | rot13涉及以下步骤:

  • 外壳创建一个管道。
  • shell fork 一个进程。子进程关闭管道的读取端并execve调用ls
  • shell fork 一个进程。子进程关闭管道的写入端并execve调用rot13
  • shell 关闭管道的两端并等待两个子进程退出。

如果两个现有进程想要相互通信,他们可以使用命名管道。 (嗯,还有文件描述符传递,但这不适合胆小的人。)

答案3

管道的外壳是公共父级,它在管道的多个成员之间建立通信通道。

任何进程都可以通过管道传输到任何其他进程。唯一的进程可以有用地通过管道连接在一起的是从标准输入读取并写入标准输出的“过滤器”。

例如,如果您发出命令

$ tail -f /etc/motd | tail -f | cat > /dev/null

ps -eaH将显示猫及其两条尾巴是调用 shell 的子级:

 1675 pts/0    00:00:00     bash
 2483 pts/0    00:00:00       tail
 2484 pts/0    00:00:00       tail
 2485 pts/0    00:00:00       cat

相关内容