有谁知道bash如何处理通过管道发送数据?
cat file.txt | tail -20
此命令是否将file.txt的所有内容打印到缓冲区中,然后由尾部读取?或者,这个命令是否逐行打印file.txt的内容,然后在每一行暂停以便尾部处理,然后要求更多数据?
我问的原因是我在嵌入式设备上编写程序,该程序基本上对某些数据块执行一系列操作,其中一个操作的输出作为下一个操作的输入发送.我想知道linux(bash)如何处理这个问题所以请给我一个通用答案,而不是具体说当我运行"cat file.txt | tail -20"时会发生什么.
提前感谢您的回复!
编辑:Shog9指出了相关的维基百科文章,这并没有直接引导我直到文章,但它帮助我找到了这个:http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation确实有我正在寻找的信息.
对不起,我很抱歉.当然你正在使用管道,当然你正在使用命令各个部分的stdin和stdout.我原以为这太明显了.
我问的是如何处理/实施.由于两个程序不能同时运行,数据如何从stdin发送到stdout?如果第一个程序生成的数据明显快于第二个程序,会发生什么?系统是否只运行第一个命令,直到它被终止或它的stdout缓冲区已满,然后转到下一个程序,依此类推,直到没有剩余的数据要处理,或者是否有更复杂的机制?
我决定写一个稍微详细的解释.
这里的"魔力"在于操作系统.这两个程序几乎同时启动,并且同时运行(操作系统将它们分配给处理器上的一些时间来运行),因为计算机上的每个其他程序同时运行的进程(包括终端应用程序和内核) .因此,在传递任何数据之前,进程正在进行必要的初始化.在您的示例中,tail正在解析'-20'参数,cat正在解析'file.txt'参数并打开文件.在某些时候,尾部将到达需要输入的点,它将告诉操作系统它正在等待输入.在某些其他方面(无论是之前还是之后,无关紧要)cat将开始使用stdout将数据传递给操作系统.这进入操作系统的缓冲区.下一次当一些数据被cat放入缓冲区后,尾部在处理器上得到一个时间片,它将检索一些在操作系统上留下缓冲区的数据(或所有数据).当缓冲区为空时,尾部必须等待cat输出更多数据.如果cat输出的数据比tail处理它的速度快得多,那么缓冲区将会扩展.cat最终将完成输出数据,但tail仍将处理,因此cat将关闭并且tail将处理缓冲区中的所有剩余数据.当操作系统不再有带有EOF的输入数据时,它将发出尾声信号.Tail将处理剩余的数据.在这种情况下,tail可能只是将所有数据接收到20行的循环缓冲区中,当操作系统发出信号表示没有更多的传入数据时,它会将最后20行转储到自己的标准输出中,该标准输出只显示在终端中.由于tail比cat更简单,所以它可能会花费大部分时间等待cat将数据放入缓冲区.
在具有多个处理器的系统上,这两个程序不仅会在同一处理器核心上共享交替的时间片,而且可能在不同的核心上同时运行.
要了解更多细节,如果在Linux中打开某种过程监视器(特定于操作系统),例如"top",您将看到一系列正在运行的进程,其中大部分都是使用0%的处理器.大多数应用程序,除非它们正在处理数据,否则大部分时间都不做任何事情.这很好,因为它允许其他进程根据需要不受限制地访问处理器.这基本上以三种方式完成.一个进程可以进入sleep(n)样式指令,它基本上告诉内核在给它另一个时间片工作之前等待n毫秒.最常见的程序需要等待来自另一个程序的东西,比如'tail'等待更多数据进入缓冲区.在这种情况下,当有更多数据可用时,操作系统将唤醒进程.最后,内核可以在执行过程中抢占进程,为其他进程提供一些处理器时间片.'cat'和'tail'是简单的程序.在这个例子中,tail花费大部分时间等待缓冲区上的更多数据,而cat花费大部分时间等待操作系统从硬盘驱动器检索数据.瓶颈是文件存储在其上的物理介质的速度(或慢度).第一次运行此命令时可能检测到的明显延迟是磁盘驱动器上的读取头寻找"file.txt"所在硬盘驱动器上的位置所需的时间.如果再次运行该命令,
您在计算机上执行的大多数操作都是IO绑定的,也就是说您通常在等待来自硬盘驱动器或网络设备等的数据.