檔案與輸入輸出

一切皆檔案(everything is a file)

想像一間工作坊,裡頭每個工具——電鑽、水管、收音機、信箱——都有同一種把手。你只需學會一種握法,就能操作它們全部。Unix 為電腦做了這個設計選擇:讓五花八門、性質迥異的東西看起來都像檔案,於是同一小撮操作就能作用在它們全部之上。

具體來說,「一切皆檔案」意指磁碟檔案、目錄、終端機、鍵盤、網路連線、程式之間的管線,甚至某些核心內部資訊,全都透過檔案描述符與同一組呼叫來存取——open()、read()、write()、close()、lseek()。一個從鍵盤讀取的程式和一個從檔案讀取的程式,都只是對某個描述符呼叫 read();它們往往不需要知道、也不在乎另一端是哪種東西。/dev 底下的特殊裝置檔案就以這種方式暴露硬體:把位元組寫進 /dev/null 會被丟棄,從 /dev/urandom 讀取會得到隨機位元組,全都透過尋常的 read 與 write。這就是為什麼重導向與管線如此強大——一個讀 fd 0、寫 fd 1 的程式,可以被接到檔案、終端機或另一個程式上,而不必改動一行。

為何重要:這個統一介面是 Unix 最深刻的理念之一,也是類 Unix 系統能由小工具組合得如此漂亮的原因。不過這句口號是個簡化——並非字面上一切都是檔案(例如網路通訊端就需要 connect()、accept() 這類純檔案沒有的額外呼叫),而且你從管線或通訊端讀到的東西,行為也跟可定位的磁碟檔案不同。但核心洞見成立:把性質天差地別的資源都導入同一個小介面,系統就能保持簡單,工具也就能無止盡地組合。

$ echo hello > /dev/null # 寫到「位元桶」,位元組消失 $ cat file.txt | wc -l # cat 的標準輸出是管線,像檔案一樣被讀取 $ wc -l < file.txt # wc 的標準輸入改成一個檔案

同一個 wc 程式從管線或從檔案讀取都無需改動——兩者都只是描述符。

這是口號,不是定律:通訊端需要自己的呼叫,而管線、終端機與通訊端上的讀取並不像磁碟檔案那樣可定位。把「一切皆檔案」當成一個強而有力的預設,而非每個 fd 行為都完全相同的保證。

又称
the file abstractionuniform I/O interface統一 I/O 介面