管道命令以什么顺序运行?


89

我从来没有真正考虑过shell如何实际执行管道命令。一直有人告诉我,“一个程序的标准输出通过管道传递到另一个程序的标准输入中”,作为思考管道的一种方式。因此,我自然而然地认为A | B,A将首先运行,然后B获得A的标准输出,并使用A的标准输出作为其输入。

但是我注意到,当人们在ps中搜索特定进程时,他们会在命令末尾包含grep -v“ grep”,以确保grep不会出现在最终输出中。这意味着在命令ps aux | grep“ bash” | grep -v“ grep”,这意味着ps知道grep正在运行,因此在ps的输出中。但是,如果ps在其输出通过管道传递到grep之前完成运行,它怎么知道grep正在运行?

flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY          TIME CMD
3773 pts/0    00:00:00 bash
3784 pts/0    00:00:00 ps
3785 pts/0    00:00:00 grep

为什么不接受答案?
törzsmókus

Answers:


64

管道命令同时运行。当您运行时ps | grep …,是先决定是开始ps还是grep开始,这是抽奖的运气(或壳的工作原理与调度程序的结合,在内核的深处进行微调),无论如何还是它们首先开始,同时执行。

这是非常常用的方法,它允许第二个程序在第一个程序完成其操作之前处理从第一个程序发出的数据。例如

grep pattern very-large-file | tr a-z A-Z

甚至在grep完成遍历大文件之前就开始以大写形式显示匹配的行。

grep pattern very-large-file | head -n 1

显示第一个匹配的行,并可能在grep完成读取其输入文件之前就停止处理。

如果您在某个地方阅读到按顺序运行管道程序的信息,请逃离本文档。管道程序可以同时运行并且始终运行。


7
这个示例的有趣之处在于,当head获得所需的一行时,它终止,并且当grep注意到这一点时,它也终止了,而无需进行任何其他工作。

我想关于管道有某种IO缓冲区...我怎么知道它的大小(以字节为单位)?我想阅读以了解更多信息?:)
n611x007

3
@naxa实际上有两个缓冲区。程序内部有stdio缓冲区grep,并且管道本身中有一个由内核管理的缓冲区。对于后者,请参阅管道缓冲区有多大?
吉尔斯

49

实际上,命令的运行顺序无关紧要,也不能保证。撇开,和的神秘细节pipe(),外壳首先创建管道,管道将成为在流程之间流动的数据,然后创建流程,并在其末端连接管道。运行的第一个进程可以阻止等待来自第二个进程的输入,或者阻止等待第二个进程开始从管道读取数据。这些等待时间可以任意长,并且没有关系。无论运行顺序如何,数据最终都会被传输并且一切正常。fork()dup()execve()


5
很好的答案,但是OP似乎认为流程是按顺序运行的。您可能在这里更清楚地说明了这些过程是同时运行的,该管道就像....桶之间的管道,水在(大约)同一时间流过所有桶。
Keith

谢谢你的澄清。我一直在阅读的资源似乎使管道程序按顺序而不是同时运行。
action_potato 2012年

若要查看以不确定的方式启动的进程,请尝试运行1000次:echo -na>&2 | echo b>&2
Ole Tange,2016年

28

冒着击败一匹死马的风险,误解似乎是

    A | 

相当于

    A > 临时文件
    B < 临时文件 
    rm 临时文件

但是,当创建Unix时,孩子们骑着恐龙去上学时,磁盘很小,而且一个比较温和的命令通常会占用文件系统中的所有可用空间。如果B是像 ,管道的最终输出可以是比中间文件更小。因此,开发了管道,而不是“先运行A,然后使用A的输出的输入运行B ”模型的简写,而是将其作为并发执行 并消除存储中间文件的一种方式在磁盘上。grep some_very_obscure_stringBA


2
这回答了为什么,因此得到我的投票。
古森林卡米

1

通常,您在bash下运行它。进程同时工作和启动,但由外壳程序并行运行。这怎么可能?

  1. 如果不是管道中的最后一个命令,请使用一对插座创建未命名的管道
  2. 叉子
  3. 在子进程中,如果需要,将stdin / stdout重新分配给套接字(对于管道stdin中的第一个进程未重新分配,最后一个进程及其stdout相同)
  4. 在子EXEC指定的命令中,带有清除原始外壳程序代码的参数,但保留所有被它们打开的套接字。子进程ID将不会更改,因为这是相同的子进程
  5. 与child同时执行,但在主shell下并行执行步骤1。

系统无法保证执行exec的速度和指定命令的启动速度。它独立于外壳,但独立于系统。这是因为:

ps auxww| grep ps | cat

一次显示grep和/或ps命令,然后下一步。这取决于内核使用系统exec函数真正启动进程的速度。


1
并发执行意味着两个或多个进程在同一时间范围内执行,通常它们之间具有某种依赖性。并行执行意味着两个或多个进程同时执行(例如,同时在不同的CPU内核上执行)。并行性与问题无关,也不与“ exec()执行速度”有关,而是exec()与管道中程序的调用和执行如何交织在一起
Thomas Nyman 2013年
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.