当前位置: 首页 > 面试题库 >

重击管道处理

余阳秋
2023-03-14
问题内容

有谁知道bash如何通过管道发送数据?

cat file.txt | tail -20

此命令是否将file.txt的所有内容打印到缓冲区中,然后由tail读取?还是说,此命令是逐行打印file.txt的内容,然后在每一行停顿以进行尾部处理,然后请求更多数据?

我问的原因是我要在嵌入式设备上编写程序,该程序基本上对某些数据块执行一系列操作,其中一个操作的输出作为下一个操作的输入发出。我想知道linux(bash)是如何处理的,因此请给我一个一般性的答案,而不是我运行“
cat file.txt | tail -20”时发生的具体情况。

编辑:Shog9指出了相关的Wikipedia文章,这并没有直接带我到该文章,但是它帮助我找到了这一点:http
:
//en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation确实有我一直在寻找的信息。

对不起,我自己说不清楚。当然,您使用的是管道,当然也使用命令的各个部分的stdin和stdout。我以为这太明显了,无法说明。

我要问的是这是如何处理/实施的。由于两个程序无法一次运行,如何将数据从stdin发送到stdout?如果第一个程序生成数据的速度明显快于第二个程序,该怎么办?系统是否一直运行第一个命令,直到它终止或stdout缓冲区已满,然后继续执行下一个程序,依此类推,直到没有更多数据要处理或存在更复杂的机制为止?


问题答案:

我决定写一个更详细的解释。

这里的“魔术”在于操作系统。这两个程序的确大致在同一时间启动,并且在计算机上所有其他同时运行的进程(包括终端应用程序和内核)中同时运行(操作系统在操作系统上分配它们的时间片)。
。因此,在传递任何数据之前,进程将进行必要的初始化。在您的示例中,tail正在解析’-20’参数,而cat正在解析’file.txt’参数并打开文件。在某个时刻,尾巴将到达需要输入的位置,并将告诉操作系统它正在等待输入。在其他时间点(无论之前还是之后,都没关系),cat将开始使用stdout将数据传递到操作系统。这进入操作系统的缓冲区。猫将某些数据放入缓冲区后,下一个尾部将在处理器上获得一个时间片,它将检索一定数量的数据(或全部),从而将缓冲区留在操作系统上。当缓冲区为空时,尾部将不得不等待cat输出更多数据。如果cat输出数据的速度快于tail处理数据的速度,则缓冲区将扩展。cat最终将完成数据的输出,但是tail将仍在处理中,因此cat将关闭,并且tail将处理缓冲区中的所有剩余数据。当它们不再具有EOF的传入数据时,操作系统将发信号通知尾巴。尾巴将处理剩余的数据。在这种情况下,tail可能只是将所有数据接收到20行的循环缓冲区中,当操作系统发出信号通知它不再有传入数据时,它将最后二十行转储到自己的标准输出中,该标准输出仅显示在终端中。由于tail是比cat更简单的程序,因此它可能会花费大部分时间等待cat将数据放入缓冲区。

在具有多个处理器的系统上,这两个程序将不仅在同一处理器内核上共享交替的时间片,而且可能在不同的内核上同时运行。

为了获得更多细节,如果您打开某种进程监视器(特定于操作系统),例如Linux中的“
top”,您将看到正在运行的进程的完整列表,其中大多数进程实际上使用了0%的处理器。除非要处理数据,否则大多数应用程序会花费大部分时间不做任何事情。这很好,因为它允许其他进程根据其需求不受限制地访问处理器。这基本上是通过三种方式完成的。进程可以进入sleep(n)样式的指令,在该指令中,它基本上告诉内核等待n毫秒,然后再给它提供另一个工作时间片。通常,程序需要等待另一个程序的响应,例如“尾巴”等待更多数据进入缓冲区。在这种情况下,当有更多数据可用时,操作系统将唤醒该过程。最后,内核可以在执行过程中抢占一个进程,从而为其他进程提供一些处理器时间片。“猫”和“尾巴”是简单的程序。在此示例中,tail花费大部分时间等待缓冲区中的更多数据,而cat花费大部分时间等待操作系统从硬盘驱动器中检索数据。瓶颈是文件存储在其上的物理介质的速度(或速度)。您可能会在首次运行此命令时检测到的可感知延迟是磁盘驱动器上的读取磁头搜索到硬盘驱动器上“
file.txt”所在位置所花费的时间。如果您第二次运行该命令,

您在计算机上执行的大多数操作都受IO约束,也就是说,您通常在等待数据来自硬盘驱动器或网络设备等。



 类似资料:
  • 我正在尝试使用动态ChannelHandler管道实现Netty 4. X。正如人们建议的“出于性能考虑,在运行时使用调用而不是管道修改”,我实现了一个Server、一个RouterInoundHander和一个Client来测试这个理论。但它不起作用。这是我的代码 计算机网络服务器 RouterInboundHandler 和客户 如代码所示,在Channel的连接初始化阶段创建了Channel

  • 问题内容: Python的多处理程序包中的队列和管道之间的根本区别是什么? 在什么情况下应该选择一种?什么时候使用比较有利?什么时候使用比较有利? 问题答案: A只能有两个端点。 一个可以有多个生产者和消费者。 何时使用它们 如果您需要两个以上的交流点,请使用。 如果您需要绝对的性能,那么a会更快,因为它建立在之上。 绩效基准 假设您要生成两个进程并在它们之间尽快发送消息。这些是使用和进行类似测试

  • 问题内容: 我正在使用以下node.js代码从某些url下载文档并将其保存在磁盘中。我想知道何时下载该文档。我没有看到使用pipe进行任何回调。或者,下载完成后是否可以捕获任何“结束”事件? 问题答案: 流是,因此您可以听某些事件。如您所说,有一个请求事件(以前是)。 有关可用的事件的更多信息,请查看流文档页面。

  • 我有一个shell命令,它接受管道作为输入,例如 我试过这个: 但是我没有得到想要的结果。是使用声明的列表。谢谢

  • 问题 你想以数据管道(类似Unix管道)的方式迭代处理数据。 比如,你有个大量的数据需要处理,但是不能将它们一次性放入内存中。 解决方案 生成器函数是一个实现管道机制的好办法。 为了演示,假定你要处理一个非常大的日志文件目录: foo/ access-log-012007.gz access-log-022007.gz access-log-032007.gz ..

  • 延迟严重。现代计算机可以以惊人的速度搅动数据,并且高速网络(通常具有在重要服务器之间的多个并行链路)提供巨大的带宽,但是… 该延迟意味着计算机花费大量的时间等待数据 和 这是基于连续的编程越来越受欢迎的几个原因之一。 让我们考虑一些常规的程序代码: string a = db.StringGet("a"); string b = db.StringGet("b"); 在涉及的步骤方面,这看起来大致