如何理解管道
當我只是在 bash 中使用管道時,我並沒有考慮更多。但是當我閱讀一些使用系統呼叫 pipe() 和 fork() 的 C 程式碼範例時,我想知道如何理解管道,包括匿名管道和命名管道。
經常聽到“Linux/Unix 中的一切都是文件”的說法。我想知道管道是否實際上是一個文件,以便它連接的一部分寫入管道文件,而另一部分從管道文件中讀取?如果是,匿名管道的管道文件在哪裡創建?在 /tmp、/dev 或 …?
但是,從命名管道的範例中,我還了解到使用管道比顯式使用臨時文件具有空間和時間性能優勢,這可能是因為管道的實現不涉及文件。管道似乎也不像文件那樣儲存數據。所以我懷疑管道實際上是一個文件。
關於您的性能問題,管道比文件更有效,因為不需要磁碟 IO。所以
cmd1 | cmd2
比cmd1 > tmpfile; cmd2 < tmpfile
(如果作為命名管道支持在 RAM 磁碟或其他記憶體設備上,這可能不是真的tmpfile
;但如果它是命名管道,cmd1
則應該在後台執行,因為如果管道變滿,它的輸出可能會阻塞)。如果您需要 的結果cmd1
並且仍然需要將其輸出發送到cmd2
,您應該cmd1 | tee tmpfile | cmd2
允許cmd1
和cmd2
並行執行,避免從cmd2
.如果許多程序讀/寫同一個管道,命名管道很有用。當程序的 IO 需要使用files時,它們也可能很有用。我將文件用斜體表示,因為從儲存的角度來看,命名管道並不完全是文件,因為它們駐留在記憶體中並且具有固定的緩衝區大小,即使它們具有文件系統條目(用於參考目的)。UNIX 中的其他事物具有文件系統條目而不是文件:只需考慮
/dev/null
or 中的其他條目/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"
。