管道可以用来连接同一进程的2个文件描述符吗?

时间:2017-02-26 17:19:38

标签: c pipe file-descriptor

这是我的项目声明,但我似乎并不完全理解将标准输出链接到管道的输入端(读取结束)。我不是要求解决方案,但我对这个问题意味着什么感到困惑

Project Statement

项目要求

该项目模拟Unix管道命令。父进程分叉一个孩子和 两个进程通过内核管道连接。 父进程接受两个命令行参数,这两个参数是两个独立的 可执行程序:p1和p2。父级打开内核管道并分叉子进程。该 child从父级继承open管道。 父进程将其标准输出链接到管道的输入端并关闭 输出结束,然后它用p1替换自己。子进程链接是输出的标准输入 管道的末端并关闭输入端,然后孩子用p2替换自己。

项目助手

在编写此程序时,您将学习并使用系统调用管道,dup2和execlp。 Pipe是一个非常简单的进程间通信设计,所有Unix / Linux都支持它 分布。每个管道编码为两个文件描述符的整数数组(int fd [2])。 fd [0]是 管道的输入端,fd 1是管道的输出端。子进程继承open 来自其父母的管道。在过程中立即关闭管道的未使用端是明智的。

有些人可以解释一下这行是什么意思"父进程将其标准输出链接到管道的输入端并关闭 输出结束" ,据我所知,我们无法从STDOUT_FILENO读取,因此调用dup2没有任何意义。

1 个答案:

答案 0 :(得分:1)

链接的问题图片说(在回答被写入时添加到问题的材料 - 也留在这里,因为我可以留下一些[原文]评论):

  

该项目模拟Unix管道命令。 ...

     

父进程接受两个命令行参数,这两个参数是两个独立的可执行程序: p1 p2 。父打开[sic]内核管道并分叉子进程。子进程从父进程继承开放管道。

     

父进程将其标准输出链接到管道的输入端并关闭输出端,然后用p1替换自身。子进程链接是[sic]标准输入到管道的输出端并关闭输入结束,然后子进程用p2替换自己。

     

...每个管道都被编码为两个文件描述符的整数数组(int fd [2])。 fd [0]是管道的输入端,fd [1]是管道的输出端。 ...

术语'输入结束'和'输出结束'已定义。

您只需将读取描述符(fd[0])连接到写入通道(FILENO_STDOUT),“可以完成”但通常没有意义。通道的方向是传统的,并确保程序之间的互通。但是你可以破坏一组程序的约定 - 这使得代码在其他环境中无用。除非专门创建程序p1p2以从文件描述符1(FILENO_STDOUT)读取并写入文件描述符0(FILENO_STDIN),否则由{生成的信息{1}}不会转发给p1

  • 练习中有错误。

你可以完全按照说明做,并证明它不起作用。您可以创建一个工作解决方案,以正统的方式执行操作并证明它确实有效。

我也会用术语'管道命令'来狡辩。在macOS上,有一个名为p2的实际命令:

  

NAME
  pipe - Postfix传递到外部命令

     

概要
         pipe [通用Postfix守护程序选项] command_attributes ...

     

说明
         pipe(8)守护进程处理来自Postfix队列管理器的请求,以将消息传递给外部命令。这个计划          期望从master(8)流程经理运行。

pipe(8)表示法不是命令;它是一种进程间通信的方法,IPC。

更好的描述是:

  

此项目模拟Unix shell管道符号 p1 | P2

问题标题是'管道可以用于连接同一进程的2个文件描述符吗?'标题中的问题实际上并未在问题正文中提出。标题中问题的答案是“是”。实际上,|系统调用在同一进程中创建了两个文件描述符,这两个文件描述符是连接的,这样可以从另一个文件描述符中读取写在其中一个文件描述符上的数据。这就是pipe()系统调用的重点。

如果您需要设置特定文件描述符对之间的链接,则必须先调用pipe(),然后调用pipe()两次,然后调用dup2()两次。 close()调用返回2个任意文件描述符号。 pipe()来电将所需的号码与dup2()提供的号码相关联; pipe()次呼叫会断开close()返回的号码。唯一需要注意的是pipe()返回的数字是否与所需数字冲突。然后你必须更加繁琐 - 可能两次调用pipe()使用dup()返回的描述符,两次调用pipe() close()返回的描述符,然后两次调用到pipe()将描述符从dup2()映射到所需的数字,然后再调用dup()来关闭close()中的描述符。 (注意dup()为您选择文件描述符; dup()允许您指定返回的文件描述符。)

dup2()仍然有可能返回所需的两个描述符中的一个;然后其中一个pipe()调用返回两个描述符中的另一个。只需在序列中添加另一个dup()即可。在致电dup()之前,请勿致电close()