[譯] 在 UNIX 中,一切皆文件

爲了有計劃的發展架構設計、界面、文化和開發路線,UNIX 系統明確了一系列統一的概念和創想。這幾點裏面最重要的一點莫過於一句咒語:「一切皆文件」,被普遍認爲是 UNIX 的定義之一。mysql

最主要的設計原則是提供一個訪問大範圍輸入/輸出資源(包括文件、文件夾、硬盤、CD-ROM、調制解調器、鍵盤、打印機、顯示器、終端機甚至跨進程和網絡通信)的統一的範例。竅門是提供一個全部這些資源的抽象對象,UNIX 之父把這個對象叫作「文件」。由於每一個「文件」都由同一個 API[1]暴露,因此你能夠用同一套命令來讀寫/操做磁盤、鍵盤、文件或網絡設備。git

這個基本概念有兩種含義:程序員

  • 在 UNIX 中,一切都是字節流
  • 在 UNIX 中,文件系統被用做通用的命名空間

在 UNIX 中,一切都是字節流

在 UNIX 中,文件是由什麼組成的呢?文件其實和一系列可讀寫的字節沒什麼區別。若是你有一個文件的索引(咱們稱之爲「文件描述符[2]」),那麼 UNIX 的 I/O 通道就已經準備好了,他們有着一樣的一套操做和 API —— 不管設備的類型如何、底層硬件是什麼。github

縱觀歷史,UNIX 是第一個把 I/O 抽象成一個統一的概念和一系列原語的系統。那時,大部分操做系統爲每一種或一類設備提供不一樣的 API。一些早期的微型計算機操做系統甚至須要你使用多個命令去拷貝文件 —— 由於每一個命令對應指定的軟盤大小!sql

對於大多數程序員和用戶來講,UNIX 向他們暴露了:shell

  • 硬盤中的文件服務器

  • 文件夾網絡

  • 連接架構

  • 大容量存儲設備(例如:硬盤、CD-ROM、磁帶、USB 設備)tcp

  • 跨進程通訊(例如:管線、共享內存、UNIX 套接字)

  • 網絡通訊

  • 可交互終端

  • 幾乎其餘全部設備(例如:打印機、顯卡)

對於字節流這種形式你能夠:

  • read(讀)
  • write(寫)
  • lseek(指針移動)
  • close(關閉)

統一的 API 特性對於 UNIX 程序來講是基礎也是很是有效的:在 UNIX 中你能夠很很輕鬆地編寫一個處理文件的程序,由於不須要關心文件是存儲在本地磁盤中、儲存在遠程網絡驅動器上、在互聯網中傳播、經過用戶互動輸入,仍是經過其餘程序在內存中生成。這顯著下降了程序的複雜性、減緩了開發者的學習曲線。而且,UNIX 架構的這個基礎特性也讓程序組合到一塊兒很是簡單(你只須要傳輸兩個特殊的文件:標準輸入和標準輸出)。

最後請注意,當全部的文件提供一致的 API 時,一些特殊類型的設備可能會不支持某些操做。舉個很明顯的例子,你不能夠在鼠標設備上使用 lseek命令,或在 CD-ROM 設備上使用 write命令(假設你的 CD 是隻讀的)。

文件系統有通用命名空間

在 UNIX 裏,文件不只僅是有一致 API 的字節流,並且能夠被統一的方式索引:文件系統有着通用命名空間。

全局命名空間和掛載機制

UNIX 的文件系統路徑爲標籤資源提供了一致的全局方案,從而能夠忽略他們的物理地址。舉幾個例子,你可使用 /usr/local命令訪問一個本地文件夾、/home/joe/memo.pdf命令訪問一個文件、/mnt/cdrom命令訪問 CD-ROM、/usr命令訪問網絡驅動器上的一個文件夾、/dev/sda1命令訪問硬盤分區、/tmp/mysql.sock命令訪問 UNIX 域名套接字、/dev/tty0命令訪問終端,甚至使用 /dev/mouse命令來訪問鼠標。這些通用命名空間一般看起來像一個文件層級或文件夾,其實就像前面舉的例子,這些只是一個方便的抽象概念,一個文件路徑能夠引用一切東西:一個文件系統、一個設備、一個網絡共享或信道。

命名空間是分層的,全部的資源均可以從根文件夾(/)訪問到。你可使用一樣的命名空間來訪問多個文件系統:你只是在命名空間的指定的位置(好比 /backups)「鏈接」了一個設備或文件系統(好比外置硬盤)。用 UNIX 術語來講,這個操做叫作 掛載mounting)一個文件系統,你鏈接文件系統的命名空間位置叫作 掛載點mount point)。你能夠經過給掛載的文件系統中的全部資源添加以掛載點命名的前綴,就像訪問通用命名空間的一部分同樣,來訪問它的全部資源(好比 /backups/myproject-Oct07.zip這個文件)。

當不一樣的資源會被明顯覆蓋的狀況下,我剛剛描述的掛載機制在創建一個統一的、明確的命名空間時就相當重要。對比一下這種命名空間和微軟操做系統中的文件系統命名空間 —— MS-DOS 和 Windows 把設備視爲文件可是 不會把文件系統放在通用命名空間中,它的命名空間是分區的而且每一個物理存儲地址被視爲獨特的實體[3]C:\是第一個硬盤,E:\是 CD-ROM 設備等等。

僞文件系統

早期,UNIX 由於提供全局 API 以及將設備掛載到統一的文件系統命名空間的特性,大幅提高了輸入/輸出資源的集成度。這個方法是如此成功,以致於從那時開始有一種將更多資源和系統服務暴露爲文件系統全局命名空間的趨勢。Plan 9 是這種作法的先驅,而如今全部新的 UNIX 系統都這麼作了。

這種方法致使產生了許多 僞文件系統,這些系統看起來和通常的文件系統同樣,可是能夠存取沒有直接關聯傳統文件系統的資源。好比你可使用僞文件系統來查詢控制進程、存取內核內部或創建 TCP 鏈接。這些僞文件系統具備文件系統語義,能夠展現分層信息,併爲大部分對象提供了統一存取的方式。僞文件系統有時也被稱爲虛擬文件系統,特色是沒有物理設備也沒有備份存儲器,只依靠內存來工做。

僞文件系統的例子:

  • procfs(/proc):proc 文件系統包含一個特殊文件層,這個文件層能夠用來查詢或控制運行中的進程,或經過標準文件入口(大部分基於文本)一窺內核內部文件。
  • devfs(/devor /devices):devfs 將全部系統中的設備以動態文件系統命名空間呈現。devfs 也能夠經過內核設備驅動直接管理這些命名空間和接口,以此來提供智能的設備管理 —— 包括設備入口註冊/反註冊。
  • tmpfs(/tmp):臨時文件系統的內容會在重啓時消失,tmpfs 是爲速度和效率而設計的,具備動態文件系統大小、用以空間清理的顯式回退等特性。
  • portalfs(/p):經過 BSD 門戶文件系統,你能夠將一個服務器進程鏈接到文件系統通用命名空間上。這樣能夠提供明確的經過文件系統對網絡服務的存取過程。好比一個 App 能夠經過打開一個合規的文件 /p/tcp/ph7spot.com/smtp來和 ph7spot.com上的 SMTP 服務器進行交互。門戶文件系統很神奇,由於它在文件系統中能夠提供套接字語義,還能夠被 UNIX 系統工具傳輸和使用(好比:catgrepawk等等)—— 甚至能夠經過 shell 來使用!
  • ctfs(/system/contract):協定文件系統做爲一個以文件爲基礎的接口的 Solaris 協定子系統。Solaris 協定爲各類各樣的事件和失敗狀況定義了一個進程或進程組的表現形式 —— 好比,進程中止時重啓。 Solaris 協定爲諸如羣集故障轉移軟件,批處理排隊系統和網格計算引擎等環境中的軟件管理和監視提供了很是高級的功能。

可以經過文件系統語義進行管理的系統資源究竟涉及多麼大的範圍,上面的例子可讓你對有一個清楚的認識了。

結論

在現代的 UNIX 操做系統中,全部設備和大部分進程間通訊在文件系統層級都以文件或僞文件的形式查看和管理。「一切皆文件」的 UNIX 基礎願景和設計原則,是 UNIX 成功和長久的關鍵因素。它提供了一個有力、簡單的抽象,使得系統、工具和社區能夠在其之上創建。更重要的是它用一種專有的方式來解決問題,那就是爲連接工具和應用提供了強有力的集成和基礎組合機制。

儘管「一切皆文件」這個比喻很成功,可是一些人或多或少懷疑它的廣泛性。當每一個文件都被視爲字節流時,產生的一個後果就是元數據缺乏標準支持:爲了合適地處理一個文件,每一個應用必須想辦法計算文件類型、架構和語義。而且,爲了保存元數據,每一個處理數據流的工具必須保持元數據不變(好比照片中的 XMP 信息)。所以,儘管 UNIX 文件的一大堆字節的形態對於連接文字界面的程序極度高效,同時也嚴重限制了多媒體和二進制應用的組合。

儘管它有它的限制,但不少人也認可這個比喻的影響力,和它在操做系統一體化上的效果。自從 UNIX 第一次發佈以來,研究者們持續推動這一中心思想。好比 Plan 9 操做系統倡導一個將系統資源徹底集成的方法:Plan 9 願景的基礎就是這樣的目標 —— 不只僅設備和信道,而是將 全部系統接口經過文件系統表明。好比 Plan 9 的設計人員注意到在 UNIX 中,網絡設備不能 徹底地被視爲合格的文件:它們經過套接字存取,而套接字有特有的打開語義而且屬於一個不一樣的命名空間(因特網套接字的主機和端口)。Plan 9 實現而且證實了,你能夠在一個全局命名空間裏成功的統一全部本地和遠程設備。這個想法最終以 portalfs的形式在 UNIX 中實現。

其餘來源於 Plan 9 的創新的概念也是基於「UNIX 中,一切皆文件」原則建立的。好比 Plan 9 在統一命名空間設計之上提供了另外一個抽象層:文件系統命名空間能夠被每一個用戶、每一個進程自定義,甚至動態調整[4]。最後,Plan 9 證實了「UNIX 中,一切皆文件」這個比喻,能夠被在更大的層面上實現。事實上,這個基礎概念在現代 UNIX 操做系統中正被繼續發揚光大[5]

參考文獻

  • 一本了不得的書 —— 《The Art of UNIX Programming》,Eric S. Raymond 著。
  • 《The Elements of Operating-System Style》和《Problems in the Design of UNIX》兩章對本文有很大幫助。
  • 《10 Things I Hate About (U)NIX》,David Chisnall 著。
  • 「Linux 情報項目」中的掛載定義。
  • Wikipedia 上的 《UNIX File Types》。
  • 《Understanding UNIX Concepts》,USAIL (UNIX System Administration Independent Learning) 著。
  • 《文件系統層級標準》。
  • 《proc 文件系統》,Redhat 出品。
  • 《BSD 系統下的模塊化用戶模式文件系統》。
  • 《Self-Healing in Modern Operating Systems》,Michael W 著。幫你更深刻地理解 Solaris 協議子系統。

做者:Wy_連接:https://juejin.im/post/5b652d346fb9a04fc03129e6來源:掘金著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索