為什麼第二個命令不等待第一個(管道)的輸出?
我目前正在閱讀 M. Bach 的“UNIX® 作業系統的設計”。
我讀到了主 shell 循環。看
if (/* piping */)
塊。如果我理解正確,管道允許將第一個命令輸出視為第二個命令輸入。如果是這樣,為什麼沒有使第二個命令等待第一個命令終止的程式碼?如果沒有這個命令,管道似乎是無稽之談:第二個命令可以在其輸入未準備好的情況下開始執行。
第二個命令可以在其輸入未準備好的情況下開始執行。
確實如此。這沒什麼不好。
在管道
producer | consumer
中,兩側同時執行¹。消費者不等待生產者完成。它甚至不關心生產者是否已經開始。消費者需要的只是一個讀取輸入的地方。一旦pipe
呼叫創建了管道,這個地方就存在。從管道中讀取是一個阻塞操作。如果尚未將數據寫入管道,則讀取器將阻塞。當數據寫入管道時,讀取器將被解除阻塞。更一般地,如果管道上沒有可用數據,則讀取器會阻塞。從管道讀取數據會消耗它。因此,生產者是否在消費者開始閱讀時開始寫作並不重要。消費者只會等到生產者寫入一些數據。
消費者在數據可用時立即接收數據。²它通常以塊的形式讀取和處理數據。大多數消費者在開始處理之前不需要擁有所有數據。如果消費者確實需要所有可用數據,它會將其儲存在記憶體或臨時文件中並等待輸入結束。
由於生產者和消費者是獨立的程序,因此它們是同時執行的。其中一個可能正在執行的事實並不能阻止另一個執行。如果生產者和消費者都需要 CPU 時間,核心將在它們之間(以及任何其他需要 CPU 時間的程序之間)共享 CPU。因此,即使消費者正在初始化,或者正在處理一些數據,生產者也可以執行並產生更多數據。
¹您可以說它們並行執行。這在技術上不正確,但足夠接近。
²實際上,生產者可以在內部緩衝數據。但是一旦生產者真正將數據寫入管道,消費者就可以讀取它。