天天看點

devfs

Devfs,也叫裝置檔案系統(Device Filesystem),設計它的唯一目的就是提供一個新的(更理性的)方式管理通常位于 /dev 的所有塊裝置和字元裝置。您也許知道,典型的 /dev 樹包含數百個塊特殊檔案和字元特殊檔案,它們全都在根檔案系統上。每個特殊檔案都可以讓使用者空間程序輕松地與核心裝置實作互動。舉例來說,通過對這些特殊 檔案執行操作,您的 X 伺服器就能夠通路視訊硬體, fsck 可以執行檔案系統檢驗, lpd 可以通過并行端口向列印機發送資料。

實際上,通常 Linux 和 Unix 更“酷”的方面是,裝置不是簡單地隐藏在晦澀的 API 之後,而是真正地與普通檔案、目錄和符号連結一樣存在于檔案系統上。因為字元和塊裝置是映射到普通檔案系統名稱空間的,我們通常可以用有意義的方式來與硬 件互動,可以僅使用标準 Unix 指令,如 cat 和 dd 。除了有趣之外,這還使我們有更強的能力,并提高生産力。

裝置管理問題

然而,雖然裝置特殊檔案本身是一件好事情,但典型的 Linux 系統以一種不太理想而且麻煩的方式管理這些特殊檔案。 如今,Linux 支援 很多 不 同種類的硬體。這意味着嚴格意義上我們中絕大多數在 /dev 中都有數百個特殊檔案來表示所有這些裝置。還不止這樣,這些特殊檔案中大多數甚至不會映射到系統中存在的裝置上(但需要它們存在,隻是考慮到我們最終會在 系統中添加新的硬體/驅動器),這讓事情變得更令人困惑。

僅從這個方面來看,我們就知道 /dev 需要徹底檢修,而建立 devfs 的明确目的就是讓 /dev 變回原形。為了很好地了解 devfs 是怎樣解決絕大多數 /dev 管理問題的,我們從裝置驅動程式的角度來看看 devfs。

devfs

裝置管理内幕

為了很好地了解 devfs ,最好是先了解從裝置驅動程式的角度來看 devfs 是怎樣改變事物的。傳統地(不使用 devfs),根據是否注冊在 塊 裝置或 字元 裝置,基于核心的裝置驅動程式通過調用 register_blkdev() 或 register_chrdev() 向系統的其餘部分注冊裝置。

您必須提供一個 主裝置号 (一個無符号 8 位整數)作為 register_blkdev() 或 register_chrdev() 的參數;然後,在裝置注冊之後,核心就會知道這個特定的主裝置号對應于執行 register_--?dev() 調用的特定裝置驅動程式。

那麼,裝置驅動程式開發人員為調用 register_--?dev() 提供的主裝置号 應該 是什麼呢?如果開發人員不打算将裝置驅動程式與外界共享,那麼什麼号碼都可以,隻要它與目前核心使用的其它主裝置号都不沖突即可。開發人員還可以選擇動态地配置設定 register_--?dev() 調用的裝置的主裝置号。然而,這樣的解決方案通常隻是在驅動程式不會被其它人使用的情況下可行。

擷取号碼

然而,如果開發人員想讓驅動程式與外界共享(大多數 Linux 開發人員常常采用這一方法),那麼僅僅從“真空”中抽一個主裝置号或者使用動态的主裝置号配置設定就不行了。相反,開發人員必須聯系 Linux 核心開發人員,這樣他(她)的特定的裝置才能配置設定一個“正式”主裝置号。那麼,在整個 Linux 世界中,這個特定的裝置(也 隻有 這個裝置)才會被關聯到那個特定的主裝置号。

有一個“正式的”主裝置号很重要,因為要與特定的裝置互動,管理者必須在 /dev 建立一個特殊檔案。當裝置節點(特殊檔案)建立後,它使用的主裝置号必須同核心内部使用的完全相同。這樣,程序對裝置執行操作時,核心就會知道應該引用什 麼裝置驅動程式。讓特殊檔案到核心驅動程式的映射成為可能的是主裝置号,而不是真實的裝置名稱(它和非 devfs 系統無關)。

一旦裝置驅動程式具備正式主裝置号,裝置就可以被公開使用了,裝置節點也就可以開始并入不同分發版的 /dev 樹,還有它們的正式 /dev/MAKEDEV 腳本(用來幫助超級使用者用正确的主從裝置号、權限和所有權建立裝置節點的特殊腳本)中。

傳統的問題

不幸的是,這種方法有很多可伸縮性問題。不僅裝置驅動程式開發人員聯系核心開發人員來擷取正式主裝置号是一件讨厭的事,核心開發人員弄清他們怎樣分 配所有這些主裝置号甚至更加惱人。這種任務在很多方面很象系統管理者跟蹤公司區域網路靜态 IP 位址配置設定的工作 ― 這并不十分有趣。正如系統管理者可以利用 DHCP 來緩解這種管理負擔,如果裝置注冊有某種類似的方法就好了。

不隻是這樣,Linux 還正在耗盡主裝置号和副号碼。雖然這種問題可以通過簡單地擴充主裝置号和副号碼使用的位數,首先維護這些主裝置号映射就很讨厭了,是以我們又在考慮有沒有更好的方法來處理這些事情。幸運的是,有這樣的方法;進入 devfs。

進入 devfs

devfs_register()

這裡是對 devfs 如何一下子處理事情和解決這些問題的一個簡單明了的快速綱要。一旦 devfs 被正确配置(包括在核心添加 devfs 支援和對啟動腳本進行一些稍複雜的更改),超級使用者重新啟動系統。然後核心開始啟動,裝置驅動程式開始向系統的剩餘部分注冊裝置。您會記起在非 devfs 系統上, register_blkdev() 和 register_chrdev() 調用(連同提供的主裝置号)正是用于這一目的。然而,現在啟用了 devfs,裝置驅動程式是用一種新的、改進了的核心調用來注冊裝置,稱為 devfs_register() 。

這裡是 devfs_register() 調用有趣的地方。雖然為了相容性目的指定主裝置号和副号碼作為參數是可能的,但不再需要這樣了。相反, devfs_register() 調用接受 裝置路徑(就是它在 /dev 下可能的出現形式) 作為參數。舉例來說,假設 foo 裝置驅動程式希望使用 devfs 注冊裝置。它會提供一個 foo0 的參數給 devfs_register() ,進而告訴核心應該在 devfs 名稱空間的根目錄建立一個新的 foo0 裝置。相應的, devfs_register() 在 devfs 名稱空間的根目錄添加 foo0 裝置節點,并記錄這個新的 foo0 節點應該映射到核心中的 foo 裝置驅動程式。

運作的 Devfs

一旦所有裝置驅動程式啟動并向核心注冊适當的裝置,核心就啟動 /sbin/init 和系統初始化腳本開始執行。在啟動過程初期(在檔案系統檢查前),rc 腳本将 devfs 檔案系統安裝在 /dev 中,/dev 包含了 devfs 名稱空間的表達。這意味着在安裝 /dev 後,所有注冊的裝置(如上面的 /dev/foo0 )都可以通路,就象在非 devfs 上一樣。當它們被通路時,核心 通過 devfs 裝置名稱 映射到合适的裝置驅動程式,而不是通過主裝置号。

這種系統的優點是,所有需要的裝置節點(沒有别的了)都由核心自動建立。這不僅僅意味着不再需要 MAKEDEV (因 為所有注冊的裝置都隻“出現”在 /dev 中),還意味着 /dev 不再被成百個“無用的”裝置節點所充斥。實際上,使用 devfs,您可以隻要檢視 /dev 就知道系統上有什麼裝置。是以,如果您有一台支援熱插拔的膝上型電腦,這意味着您甚至可以在您從系統中插入和拔出 PC 卡時魔術般地讓裝置從 /dev 中出現和消失。這讓 devfs 成為對以前笨拙局面的一個非常徹底和實用的解決方案。

devfs 的優點

Devfs 讓很多事變得容易許多。請考慮一下建立一張 Linux 可引導CD光牒的問題,它包括一個位于 CD 上的引導裝載器、一個 initrd、一個核心和一個回送檔案系統。當 CD 引導時,引導裝載器裝載核心和 initrd,然後核心執行 initrd 上的 /linuxrc 腳本。 /linuxrc 的主要任務是安裝 CD,進而使回送檔案系統本身也可以被安裝和通路。

沒有 devfs, linuxrc 就需要“檢視” /dev 中的很多特殊檔案,它們可能有也可能沒有表示連接配接到系統的真實硬體。例如, linuxrc 會需要檢測 /dev/hdc、/dev/scd0、/dev/hdb 和其它的裝置以檢測“活動的”CD光牒驅動器裝置。在檢測程序中,很可能命中幾個“無用的”裝置節點。

然而,使用 devfs, linuxrc 隻在 /dev/cdroms 中尋找,它包含了系統中所有和 活動的 光 盤驅動器相關聯的特殊檔案,不管是 IDE 的還是 SCSI 的。由于這種便捷的新式 devfs 約定,再不需要猜測了;隻有活動的裝置才會列出,而且裝置檢測代碼甚至不必擔心底層的CD光牒驅動器的細節,比如說它使用什麼 IDE 通道或者什麼 SCSI ID。實際上,這是 devfs 的另一個主要好處;在我下一篇文章中,我們會看到 devfs 下 /dev 中的裝置有全新的預設位置。

實際上,如果您想通路一個特定的塊裝置(如磁盤、分區、CD光牒驅動器等等),事實上有 幾個不同的 特殊檔案可以引用。例如,我的伺服器隻有一個 SCSI CD光牒驅動器;如果啟用了 devfs,我就可以通過安裝 /dev/cdroms/cdrom0 或 /dev/scsi/host0/bus0/target4/lun0/cd 通路它。兩種都引用同一個裝置,我可以引用我認為最友善的特殊檔案。如果願意,我還可以使用一種老式的裝置名稱(/dev/sr0)通路CD光牒驅動器,這都是因為有一個非常便捷的叫 devfsd 的小程式。 devfsd 是一個有功能很多的程式,它負責建立老式的“相容性”特殊檔案,還允許您以很多種方式自定義 /dev。在我的下一篇文章中,我們會詳細讨論 devfsd ,到時我會一直引導您啟動 devfs 并在您自己的系統上運作它。在那之前,請參考下面的參考資料以了解更多關于 devfs 的資訊。

繼續閱讀