为什么第二个命令不等待第一个命令(管道)的输出?

为什么第二个命令不等待第一个命令(管道)的输出?

我目前正在阅读 M. Bach 的《UNIX® 操作系统的设计》。

我读到了有关主 shell 循环的内容。看看if (/* piping */)块。如果我理解正确的话,管道允许将第一个命令输出视为第二个命令输入。如果是这样,为什么没有代码让第二个命令等待第一个命令终止?如果没有这个命令,管道似乎毫无意义:第二个命令可以在其输入尚未准备好的情况下开始执行。

主壳循环

答案1

第二个命令可以在其输入尚未准备好的情况下开始执行。

确实如此。这没有什么问题。

在管道中producer | consumer,两侧同时运行。消费者不会等待生产者完成。它甚至不关心生产者是否已经开始。消费者所需要的只是一个读取输入的地方。一旦调用创建了管道,这个地方就存在pipe

从管道读取是阻塞手术。如果尚未将数据写入管道,则读取器会阻塞。当数据写入管道时,读取器将被解除阻塞。更一般地,如果管道上没有可用数据,则读取器会阻塞。从管道读取数据会消耗它。因此,当消费者开始读取时,生产者是否已经开始写入并不重要。消费者将等待生产者写入一些数据。

消费者在数据可用时立即接收数据。²它通常以块的形式读取和处理数据。大多数消费者在开始处理之前不需要拥有所有数据。如果消费者确实需要所有可用数据,它会将其存储在内存或临时文件中,并等待输入结束。

由于生产者和消费者是独立的进程,因此它们是并发执行的。其中一个可能正在运行这一事实并不妨碍另一个运行。如果生产者和消费者都需要 CPU 时间,内核将在它们之间(以及任何其他需要 CPU 时间的进程之间)共享 CPU。因此,即使消费者正在初始化,或者正在处理一些数据,生产者也可以运行并产生更多数据。

1你可以说它们是并行运行的。这在技术上并不正确,但足够接近。
²在实践中,生产者可以缓冲内部数据。但一旦生产者实际将数据写入管道,消费者就可以读取它。

相关内容