bash 命令中的管道如何工作?

bash 命令中的管道如何工作?

通过管道链接 bash 命令时是否发生了任何象征性的事情,或者都是计算-传递-计算-传递?

例如,在 中head t.txt -n 5 | tail -n 2,正在head t.txt -n 5计算然后tail -n 2执行它。或者首先有一些抽象告诉 shell 要读取第 3 行到第 5 行?在这个例子中可能没有什么区别,但我想在其他情况下可以。

答案1

shell 使用pipe(2)系统调用在内核中创建一个有两个文件描述符的有界缓冲区,一个使进程能够写入缓冲区,另一个使进程能够从缓冲区读取。

考虑一个简单的情况:

$ p1 | p2

在这种情况下,从概念上讲,shell 创建上述管道fork()s ,子级将其标准输出流连接到管道的写入端,然后是子级exec()s p1。接下来,shellfork()再次 s ,子级将其标准输入流连接到管道的读取端,然后是子级exec()s p2。 (我说从概念上来说因为 shell 可能会以不同的顺序执行操作,但想法是相同的。)

那时,p1p2正在同时运行。 p1将写入管道,内核会将写入的数据复制到缓冲区。 p2将从管道中读取,内核将从缓冲区中复制读取的数据。如果管道已满,则内核将阻塞p1其调用,write()直到p2从管道中读取某些内容,从而释放一些空间。如果管道为空,则内核将阻塞p2其调用,read()直到将p1更多数据写入管道。

答案2

您建议的两种型号中。计算传递-计算传递是最接近的。 shell 只是连接进程。它对他们在做什么一无所知。

除了, 执行顺序未定义。它们实际上同时运行。然而,左边的必须先输出字节,然后右边的才输入字节。数据从左向右流动。数据从第一个命令流出其标准输出,然后流入下一个进程的标准输入,在那里进行处理,然后从其标准输出出来,可以通过管道传输到另一个进程,等等等等等等

如果没有重定向><等等或从文件中读取。然后看起来像这样。

         ┌───────────┐ ┌───────────┐ ┌─────────────┐
Terminal⇨│Process one│⇨│Process two│⇨│Process Three│⇨Terminal
         └───────────┘ └───────────┘ └─────────────┘

相关内容