运行管道命令时,Linux实用程序是否聪明?


23

我只是在终端中运行一些命令,然后开始思考,在运行管道命令时,Unix / Linux是否采用快捷方式?

例如,假设我有一个包含一百万行的文件,其中前十行包含hello world。如果运行该命令grep "hello world" file | head,第一个命令找到10行后会立即停止,还是先继续搜索整个文件?


2
这就是为什么gnu grep具有该-m参数。
Paul Tomblin,2012年

3
终端与此无关。管道命令由外壳程序管理。
基思·汤普森

@KeithThompson请原谅我的无知,我对术语并不了解,不确定是将其称为终端,shell还是命令行。随时建议对我的问题进行编辑:)
DisgruntledGoat 2012年

Answers:


30

有点。Shell不知道您正在运行的命令将执行什么操作,它只是将一个命令的输出连接到另一个命令的输入。

如果grep发现多于10条说“ hello world”的行,head则将拥有它想要的所有10条线,然后关闭管道。这将导致grep被SIGPIPE杀死,因此不需要继续扫描非常大的文件。


2
所以我想,由于种族条件的缘故,grep可能已经读取了第11或12个模式,但可能不是10万吨?
用户未知

3
这部分取决于行的长度和管道缓冲区的大小,但是简单的答案是grep在被杀死之前将读取一定数量有限的额外数据。
dmckee 2012年

1
@userunknown,准确。
psusi 2012年

太酷了,我不知道发生了什么。我以为grep会继续将输出发送到/dev/null
空白处

15

当程序尝试写入管道并且没有从该管道读取进程时,写入器程序将收到SIGPIPE信号。程序收到SIGPIPE时的默认操作是终止程序。程序可以选择忽略SIGPIPE信号,在这种情况下,写操作会返回错误(EPIPE)。

在您的示例中,这是发生情况的时间表:

  • grephead平行的命令启动。
  • grep 读取一些输入,开始处理它。
  • 在某个时候,grep产生第一块输出。
  • head 读取第一个块并将其写出。
  • 假设在前10个匹配项之后有足够的行(否则grep可能会先终止),最终head将打印出所需的行数。此时,head退出。
  • 根据grephead处理的相对速度,grep可能已经积累了一些数据而尚未打印出来。在head退出时,grep可能正在读取输入或进行内部处理,在这种情况下,它将继续这样做。
  • 很快grep就会写出处理过的数据。届时,它将收到SIGPIPE并死亡。

很可能grep会处理多一点投入比严格意义上,但通常只有几KB:

  • head通常读取几千字节的块(因为这比read为每个字节发出系统调用更有效-这种行为称为缓冲),因此丢弃了所需最后一行之后的最后一块剩余部分。
  • 可能有一些数据在传输中,因为管道具有由内核管理的关联缓冲区(通常为512字节)。该数据将被丢弃。
  • grep可能已经积累了一些准备好成为输出块的数据(再次缓冲)。尝试刷新其输出缓冲区时,它将收到SIGPIPE。

总体而言,系统经过精心设计,因此过滤实用程序自然可以高效地运行。当输出通道消失时需要继续运行的程序必须采取忽略SIGPIPE信号的步骤。


3

排序,管道的工作方式如下:在您的情况下,它首先执行第一个命令,然后执行第二个命令。

也就是说,让我们A|B给出命令。然后不确定是先开始A还是B先开始。如果有多个CPU,则它们可能完全同时启动。管道可以容纳未定义但数量有限的数据。

如果B试图从管道读取,但没有可用数据,B则将等待数据到达。如果B正在从磁盘读取,则B可能有相同的问题,需要等到磁盘读取完成。更加接近的类比是从键盘读取。在那里,B需要等待用户键入。但是在所有这些情况下,B已经开始“读取”操作,必须等待其完成。但是,如果B某条命令仅需要部分输出,A则在B达到s输入级别的某个点之后A,SIGPIPE将终止该命令

如果A试图写入管道并且管道已满,则A必须等待管道中的一些空间可用。A如果正在写入终端,则可能会有相同的问题。终端具有流量控制功能,可以调节数据速度。无论如何,对于A,它已经开始了“写”操作,并将等待直到写操作完成。

A并且B表现为协同流程,尽管并非所有协同流程都将与管道进行通信。双方都无法完全控制对方。


1
问题是:“当B关闭管道侧面时,A会做什么?”
enzotib 2012年

2
那不是一个“折断的管道”吗?
Patkos Csaba

1
如果程序尝试从封闭的管道读取/写入封闭的管道(例如,head出口),则会在程序中出现SIGPIPE信号,并且默认行为是退出。
Lekensteyn 2012年

这究竟如何回答这个问题?似乎psusi的答案更短,更具体。
2012年

1

grep没有对管道的直接控制(它只是接收数据),而对管道没有直接的控制grep(它只是发送数据)...

什么grep,或任何其他程序做,完全取决于该方案的内部逻辑。如果您grep通过命令行选项告诉创建一个早退出-被发现,那么它将退出,否则它将进入文件的最末端以寻找模式...

终端同样与的内部操作grepshell的管道动作完全断开...终端基本上只是一个发射台和输出显示...

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.