Shell

如何理解管道

  • September 23, 2018

當我只是在 bash 中使用管道時,我並沒有考慮更多。但是當我閱讀一些使用系統呼叫 pipe() 和 fork() 的 C 程式碼範例時,我想知道如何理解管道,包括匿名管道和命名管道。

經常聽到“Linux/Unix 中的一切都是文件”的說法。我想知道管道是否實際上是一個文件,以便它連接的一部分寫入管道文件,而另一部分從管道文件中讀取?如果是,匿名管道的管道文件在哪裡創建?在 /tmp、/dev 或 …?

但是,從命名管道的範例中,我還了解到使用管道比顯式使用臨時文件具有空間和時間性能優勢,這可能是因為管道的實現不涉及文件。管道似乎也不像文件那樣儲存數據。所以我懷疑管道實際上是一個文件。

關於您的性能問題,管道比文件更有效,因為不需要磁碟 IO。所以cmd1 | cmd2cmd1 > tmpfile; cmd2 < tmpfile(如果作為命名管道支持在 RAM 磁碟或其他記憶體設備上,這可能不是真的tmpfile;但如果它是命名管道,cmd1則應該在後台執行,因為如果管道變滿,它的輸出可能會阻塞)。如果您需要 的結果cmd1並且仍然需要將其輸出發送到cmd2,您應該cmd1 | tee tmpfile | cmd2允許cmd1cmd2並行執行,避免從cmd2.

如果許多程序讀/寫同一個管道,命名管道很有用。當程序的 IO 需要使用files時,它們也可能很有用。我將文件用斜體表示,因為從儲存的角度來看,命名管道並不完全是文件,因為它們駐留在記憶體中並且具有固定的緩衝區大小,即使它們具有文件系統條目(用於參考目的)。UNIX 中的其他事物具有文件系統條目而不是文件:只需考慮/dev/nullor 中的其他條目/dev/proc.

由於管道(命名和未命名)具有固定的緩衝區大小,因此對它們的讀/寫操作可能會阻塞,從而導致讀/寫過程進入 IOWait 狀態。另外,從記憶體緩衝區讀取時,您何時收到 EOF?這種行為的規則是明確定義的,可以在 man 中找到。

管道(命名和未命名)不能做的一件事是在數據中回溯。由於它們是使用記憶體緩衝區實現的,因此這是可以理解的。

關於"everything in Linux/Unix is a file",我不同意。命名管道具有文件系統條目,但不完全是文件。未命名的管道沒有文件系統條目(可能在 中除外/proc)。但是,UNIX 上的大多數 IO 操作都是使用需要文件描述符的讀/寫函式完成的,包括未命名的管道(和套接字)。我不認為我們可以這麼說"everything in Linux/Unix is a file",但我們肯定可以這麼說"most IO in Linux/Unix is done using a file descriptor"

引用自:https://unix.stackexchange.com/questions/18117