答案1
让我们假设 shell 在终端上运行的常见情况。 shell 的所有 stdin、stdout、stderr 都连接到该终端,从其中读取是读取用户的输入,向其中写入则打印内容供用户读取。
现在,当 shell 启动命令时,该命令还会将所有 fd 连接到终端。 shell 启动的下一个命令也是如此。就像这样:
+---------------+ +---------------+
| first cmd | | other cmd |
|stdin stdout | |stdin stdout |
+---------------+ +---------------+
| | | |
| | | |
| | | |
[------------------ tty -----------------]
现在,你说:
我的第一个想法是用第一个进程的标准输出更改第二个进程的标准输入
但是如果你要交换上面的两个 fd,结果不会有什么不同,所有 fd 之前都连接到 tty,所以在交换之后所有 fd 都会连接到 tty。
现在,如果您的意思是从 tty 端分离其中一个 fd,那么,这实际上并不是它的工作原理。 fd 更像是指向内核数据结构的指针,指向 tty 的 fd 与指向管道或网络套接字的 fd 不同。或者,换个角度来看,fd 只是进程和操作系统之间“连接”的进程端。
因此,您需要另一种 fd,它可以连接到操作系统端的另一种东西。例如,管道。管道仍然不仅仅是两个进程之间的连接,但是两个连接进程和操作系统之间:
+---------------+ +---------------+
| first cmd | | other cmd |
|stdin stdout | |stdin stdout |
+---------------+ +---------------+
| | | |
| | | |
| [-w-- pipe driver -----r-] |
| |
[------------- tty driver ---------------]
(请注意,我上面假设 tty fd 都是开放的,可以读取和写入。这就是我研究过的 Linux 系统上的情况,因此实际上可以写入 stdin,或将 stdin fd 复制到 stdout。如果它们以只读/只写模式打开,那么这是行不通的,Linux 管道始终是单向的,并且具有不同的读取端和写入端。)
答案2
假设您不使用管道。您的第一个进程可以写入标准输出。你的第二个进程可以读取标准输入。
很容易关闭标准输入第二个进程的,但是你打开什么来访问标准输出第一个过程的? (提示:你不能。)
因此,您创建一个具有众所周知端点的管道,可以打开该管道进行写入和读取。