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


8

这个页面,从设计和4.4BSD操作系统的实现,据说:

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

但是,如果我记录正确,则创建新流程的唯一方法是fork使用现有流程。因此,我真的看不到两个进程如何没有一个共同的祖先。那么,我认为任何一对进程都可以通过管道相互传递对吗?


1
如果您的问题确实是关于“共同祖先”的,那不是您所说的话。父母是祖先,但并非所有祖先都是父母。
msw

看看ps auxf关于过程祖先的想法。
2013年

@msw表示两个进程需要具有相同的直接父级吗?堂兄(即有一个共同的祖父母)还不够吗?
qdii

Answers:


7

那么,我认为任何一对进程都可以通过管道相互传递对吗?

并不是的。

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

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


4

那句话不是很清楚。首先,父级应该是祖先,因为建立管道的过程可以是父级,也可以是祖父母,也可以是祖父母或祖父母或祖父母,或者是其中一个通信过程。其次,该句子的意思不是“如果要管道,则必须存在一个共同的祖先过程”,而是“如果要管道,则必须建立一个共同的祖先过程”。

在引擎盖下,一个过程与其自身建立了一条管道。管道是一个文件描述符,与其他任何文件描述符一样,或更确切地说,是一对文件描述符,每个端点一个。创建管道的进程可以立即使用它向自身发送数据,尽管这很少有用(尽管自管道确实有其用途)。

一个典型的成语是让进程建立一个管道,然后派生一个子进程,并在父管道中关闭管道的一端,在子管道中关闭管道的另一端。这使父进程和子进程在一个方向上进行通信。如果进程需要双向通信,则它们需要两个管道(在某些unix变量中,管道是双向的除外)。

管道又被任何子代继承,因此创建管道的过程可能不会参与通信。例如,在两个外部命令(例如)之间创建的外壳中的管道ls | rot13涉及以下步骤:

  • 外壳创建一个管道。
  • Shell分叉一个进程。孩子关闭管道和电话的读端execvels
  • Shell分叉一个进程。孩子关闭管道的写端,并呼吁execverot13
  • 外壳关闭管道的两端,并等待两个子进程退出。

如果两个现有进程要相互通信,则可以使用命名管道。(嗯,还有文件描述符传递,但这不是出于胆小。)


2

管道的外壳是公用父管道,它在管道的几个成员之间建立了通信通道。

任何进程都可以通过管道传递给其他进程。可以有效地通过管道传递的唯一进程是从标准输入读取并写入标准输出的“过滤器”。

例如,如果您发出命令

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

ps -eaH 将显示猫及其两条尾巴是调用外壳的子代:

 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.