bash 指令中的管道如何運作?

bash 指令中的管道如何運作?

透過管道連結 bash 命令時是否發生了任何象徵性的事情,或者都是計算-傳遞-計算-傳遞?

例如,在 中head t.txt -n 5 | tail -n 2,正在head t.txt -n 5計算然後tail -n 2執行它。或者首先有一些抽象告訴 shell 要讀取第 3 行到第 5 行?在這個例子中可能沒有什麼區別,但我想在其他情況下可以。

答案1

shell 使用pipe(2)系統呼叫在核心中建立一個有界緩衝區,該緩衝區具有兩個檔案描述符,一個使進程能夠寫入緩衝區,另一個使進程能夠從緩衝區讀取。

考慮一個簡單的情況:

$ p1 | p2

在這種情況下,從概念上講,shell 創建上述管道fork()s ,子級將其標準輸出流連接到管道的寫入端,然後是子級exec()s p1。接下來,shellfork()再次 s ,子級將其標準輸入流連接到管道的讀取端,然後是子級exec()s p2。 (我說從概念上來說因為 shell 可能會以不同的順序執行操作,但想法是相同的。

那時,p1p2正在同時運行。 p1將寫入管道,核心會將寫入的資料複製到緩衝區。 p2將從管道中讀取,核心將從緩衝區複製讀取的資料。如果管道已滿,則核心將阻塞p1其調用,write()直到p2從管道中讀取某些內容,從而釋放一些空間。如果管道為空,則核心將阻塞p2其調用,read()直到將p1更多資料寫入管道。

答案2

您建議的兩種型號中。計算傳遞-計算傳遞是最接近的。 shell 只是連線進程。它對他們在做什麼一無所知。

除了, 執行順序未定義。它們實際上同時運行。然而,左邊的必須先輸出字節,然後右邊的才輸入位元組。數據從左到右流動。資料從第一個命令流出,從其標準輸出流出,然後流入下一個進程的標準輸入,在那裡進行處理,然後從標準輸出流出,可以透過管道傳輸到另一個進程,等等等等等等

如果沒有重定向><等等或從檔案中讀取。然後看起來像這樣。

         ┌───────────┐ ┌───────────┐ ┌─────────────┐
Terminal⇨│Process one│⇨│Process two│⇨│Process Three│⇨Terminal
         └───────────┘ └───────────┘ └─────────────┘

相關內容