特種文件系統(4)

9.4 devfssysfs

devfssysfs它們來了,真的來了,一前一後來的,來得是那麼突然,來得是那麼悄無聲息。一個臉色蒼白,蒼白得讓人不寒而慄;一個眼光深邃,深邃的讓人頓覺謙卑。人們一直在談論着它們,據說先來的已經死了,死的很透徹,是被它的門人殺死的,而且居然是後來者收買了它的門人,後來的現在還在收買其他門派的門人,正在覬覦“武林盟主”的地位。所有的事情就這麼潛移默化的變化着,輪替着。一切看似那麼平靜,平靜得已經讓讓很多人開始摩拳擦掌。在這平靜之中不知何時又要到來一場可怕的血雨腥風。

故事是這樣開始的……

9.4.1 devfs的由來

Linux,或者說類UNIX系統最“酷”的地方是,設備不是簡單地隱藏在晦澀的API之後,而是真正的與普通文件、目錄或符號連接一樣,存在於文件系統之上(還記得我們前面說過的9號計劃嘛?正是發源於此)。因爲字符設備和塊設備是映射到普通文件系統名稱空間的,這樣人們就可以通過很簡單的文件讀寫方式與硬件交互。很多時候僅使用標準的Linux命令,如catdd,就足夠了。這些映射設備的文件被合理的組織在了/dev目錄下。

devfs,也叫設備文件系統,它的唯一目的就是提供一個新的,更合理的方式管理那些位於/dev目錄下的所有塊設備和字符設備。因爲典型的Linux系統以一種不太理想,而且麻煩的方式管理這些特殊文件。

時至今日,Linux支持的硬件種類越來越多,也就意味着在/dev中的文件數量也越來越多,用數以萬計來說的確很誇張,但是要說數以千計、數以百計是絕對不過份的。只是這還不是問題的根本,最根本的是這些特殊文件是寫死的,而且大多數根本不會映射到系統中,因爲再複雜的服務器,撐死也就配備幾十個設備。顯然是使用99.9%的努力,只是爲了解決0.1%的問題。況且誰也不敢保證用戶以後不添置什麼設備,所以這些文件一個都不能動。

不過devfs誕生之際,情況沒有上面說的那麼糟糕。就是因爲devfs的生辰問題,導致了它日後的結局,我們祖先發明的生辰八字有些時候想想還是蠻有“科學”道理的。devfs誕生的太早了,它雖然對上面的問題做了一定的處理,但是有些不是很合理,具體我們後面還會說。現在要說的是,它解決了一個更要命的問題。什麼問題呢?設備號的問題。傳統的Linux設備驅動程序,要向系統提供一個文件映射,需要提供一個主設備號,而且這個主設備號必須保證唯一。由於歷史原因,早些年內存比黃金還貴,這個主設備號被設計的只有8位,顯然這是稀缺資源啊,在它面前,黃金都只能汗顏了。既然這樣,開發人員自然不能憑空臆造一個主設備號了,只能聯繫Linux內核的開發人員來申請,如果人家正忙着呢,那您就只能等,還不能歇,一歇就麻煩了,因爲等待申請的人多了去了。所以,您就甘心的在那兒耗着吧。直到人家看你是個虔誠的主兒,偶發惻隱之心,給您分配了一個“正式”的主設備號,您纔算萬事大吉收工交差。其實後面的事情遠沒有這麼簡單,只是那已經是歷史,我就不多叨嘮了。至於這種策略的後果是什麼,我不說,誰都知道。反正很難想象,早年的Linux用戶真是有夠虔誠,要不然現在還有誰會知道有Linux這個破玩意兒呢?

不管devfs的命運如何,但就僅僅是把這個濫問題給解決了,就可以稱之爲偉大,何況這只是其中的一個部分呢?

9.4.2 進入devfs

devfs是怎麼解決這個濫問題的呢?它給驅動開發人員提供了一個叫devfs_register()的內核API,這個API可以接受一個設備名稱作爲參數。調用成功後,在/dev目錄下就會出現與設備名相同的文件名。而且devfs_register仍然支持主設備號的策略,這樣可以保持向下兼容性,降低早期的設備驅動程序移植的複雜性。

一旦所有設備驅動程序啓動並向內核註冊適當的設備,內核就啓動/sbin/init進程,系統初始化腳本開始執行。在啓動過程初期,rc腳本將devfs文件系統安裝在/dev中,這樣/dev中就包含了devfs所表達的所有設備映射關係,所有註冊的設備依然可以通過/dev目錄進行訪問,用戶應用程序不用做任何修改。

這種設計的最大優點就是:所有需要的設備映射關係都由內核自動創建,因此也就不用寫死設備文件了,那麼/dev目錄下就不會充斥着大量的無用的設備文件了。在實際應用中,只要查看一下devfs,就能夠知道這個系統上有什麼設備了。

devfs讓一切變得容易了許多。最典型的就是當你編寫一個顯示實時系統信息的程序時,不用做依次輪詢哪些設備是“活躍的”這樣費時的工作。因爲只要讀取/dev下得所有信息就可以搞定。即便用戶只想查看某一個類型設備的信息,比如光驅,根據devfs的約定,只需要讀取/dev/cdroms下的所有文件即可。

在實際操作中,比如你想訪問一個特定的塊設備,還有很多不同的途徑。例如:一個服務器上,只有一個SCSI光驅;使用devfs後,就可用通過/dev/cdroms/cdrom0訪問;還通過使用/dev/scsi/host0/bus0/target4/lun0/cd訪問它。這兩種都映射了同一個設備,你可以選擇一個你認爲最方便的途徑。如果你願意,還可以使用一種老式的設備名稱/dev/sr0訪問光驅,這都是因爲有一個非常便捷的叫devfsd的小程序在幕後完成的工作。這個程序雖然小,但是功能很多。它負責創建老式的“兼容性”設備映射文件,允許你一很多方式自定義/dev

9.4.3 sysfs的由來

sysfs是後來的,收買了devfs的門徒,殺死了devfs,它用的不是錢和刀,是udev。還發表聲明公開了devfs該殺的四大罪狀。但是馬上就有人不服了:才四大罪狀,好多貪官100條大罪都犯下了,也沒判死刑不是?Linux是一個崇尚簡單的世界,只要有一條能夠說明你很麻煩,就有理由殺掉你,況四條大罪呼?那麼這四條大罪是什麼呢?

第一,不確定的設備映射,有時一個設備映射的設備文件可能不同,例如我的U盤,可能對應sda也可能對應sdb

第二,沒有足夠的主/輔設備號,當設備過多的時候,這就是一個問題。前面說過,雖然devfs已經意識到了將來的設備會很多,但是沒處理好,沒有給主/輔設備號太多的擴展餘地。

第三,dev目錄下文件太多而且不能表示當前系統上的實際設備(這個罪狀在我看來是有點牽強的,不過欲加之罪嘛)。

第四,命名不夠靈活,不能任意指定。

於是devfs死了,sysfs成爲了新的“幫主”。那麼sysfs究竟是什麼來頭呢?系出名門,出身高貴啊。

最初,當人們已經開始意識到procfs的複雜度之後,就開始想將procfs中有關設備的部分獨立出來。最開始採用ramfs(這個可以看作是RamDisktmpfs的中間產品)作爲基礎,名曰ddfs,後來發現driverfs更爲貼切。這些都是在2.5版本中內核鼓搗的。按照那個時候的內核版本號的規則,所有第二位爲奇數的版本都是實驗版,所以2.5這個內核版本對於大衆來說是不多見的。driverfs把實際連接到系統上的設備和總線組織成一個分級的文件,和devfs相同,用戶空間的程序同樣可以利用這些信息以實現和內核的交互(這個思路來自procfs),該系統是當前實際設備樹的一個直觀反映。到了2.6內核,也就是2.5的最終成型版本,新設計了一個kobject子系統,它就改變了實現策略拋棄了ramfs,利用kobject子系統來建立這些信息。當一個kobject被創建的時候,對應的文件和目錄也就被創建了,位於/sys下的相關目錄下。因此更名爲sysfs。因爲本身就源自於procfs的設計思路,因此它所提供的也是用戶空間與系統空間交換信息的接口。用戶空間工具udev就是利用了sysfs提供的信息在用戶空間實現了與devfs完全相同的功能。既然功能相同,而且是在用戶空間實現,顯然比在內核空間實現的devfs要簡單的多,安全得多,也會穩定的多。devfs被殺,也許這就是它的宿命。

9.4.4 小結

其實sysfsdevfs做比拼已經沒有實際的意義了,因爲現在顯然已經沒有任何爭端了。只是我想展現給大家還是開篇的一個主題:新的系統並不是只爲了做同樣的事情比老的系統快一點,還應該允許我們用以前完全不可能的方法來處理事情。

顯然sysfs能夠實現全部devfs的功能,而且是在用戶空間完成的。不單單是這樣。當一部並不存在的/dev節點被打開的時候,devfs會很負責的去加載這個驅動程序,sysfs卻不會做這種傻事。不過也不能說devfs傻,應該說它敬業,要很負責的告訴用戶,這個設備不存在,但是它沒有好的機制去做,只能用笨方法,讓驅動程序實際去監測設備來報告這個結果。sysfs如果只是做到這些,應該還是不能足以收買devfs的門徒的,sysfs還能給內核產生的設備名增加別名,好處就是用戶可以用自己喜歡的名字,顯然對用戶很友好。sysfs真正的徹底解決了devfs遇到的所有問題。

devfssysfs的故事講到這裏也該結束了。在如今的Linux發行版中,你再也找不到devfs的影子了,但是procfssysfs還在。sysfs如今大紅大紫,procfs的命運如何,還需要你我共同的期待。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章