linux下有專門的文件系統用來對設備進行管理,devfs和sysfs就是其中兩種。
一、devfs
devfs是在2.4內核就出現了,它是用來解決linux中設備管理混亂的問題,你查看一下/dev下的設備文件就知道其中有許多是空的(也就是沒有對應的硬件的),但是它們卻必須存在,所以這給linux設備管理帶來了很多麻煩,為了解決這個問題,linux內核開發人員開發了devfs,並用一個守護進程devfsd來做一些與以前硬件驅動兼容的事情。
devfs和sysfs都是和proc一樣,是一個虛擬的文件系統,向devfs注冊的驅動程序,devfs將會在/dev下建立相應的設備文件;但是為了兼容,devfsd這個守護進程將會在某個設定的目錄中建立以主設備號為索引的設備文件,如果不這么做,以前的許多應用將不能運行。
在2.6內核以前一直使用的是devfs,devfs掛載於/dev目錄下,提供了一種類似於文件的方法來管理位於/dev目錄下的所有設備,我們知道/dev目錄下的每一個文件都對應的是一個設備,至於當前該設備存在與否先且不論,而且這些特殊文件是位於根文件系統上的,在制作文件系統的時候我們就已經建立了這些設備文件,因此通過操作這些特殊文件,可以實現與內核進行交互。
但是devfs文件系統有一些缺點,例如:不確定的設備映射,有時一個設備映射的設備文件可能不同,例如我的U盤可能對應sda有可能對應sdb;沒有足夠的主/輔設備號,當設備過多的時候,顯然這會成為一個問題;/dev目錄下文件太多而且不能表示當前系統上的實際設備;命名不夠靈活,不能任意指定等等。
二、sysfs
sysfs是Linux 2.6所提供的一種虛擬文件系統。這個文件系統不僅可以把裝置(devices)和驅動程式(drivers)的資訊從kernel space輸出到user space,也可以用來對裝置和驅動程式做設定。
sysfs的目的是把一些原本在procfs中的,關於裝置的部份獨立出來,以[裝置階層架構}(device tree)的形式呈現。這個檔案系統由Patrick Mochel所寫,稍后Maneesh Soni撰寫 "sysfs backing store path",以降低在大型系統中對內存的需求量。
sysfs一開始以ramfs為基礎,也是一個只存在於內存中的檔案系統。ramfs是在2.4核心處於穩定階段時加入的。ramfs是一個優雅的實做,證明了要在當時仍很新的虛擬檔案系統(VFS)下寫一個簡單的檔案系統是多么容易的一件事。由於ramfs的簡潔以及使用了VFS,稍后的一些內存形式的檔案系統都以它作為開發基礎。
sysfs剛開始被命名成ddfs(Device Driver Filesystem),當初只是為了要對新的驅動程式模型除錯而開發出來的。它在除錯時,會把裝置架構(device tree)的資訊輸出到procfs檔案系統中。但在Linus Torvalds的急切督促下,ddfs被轉型成一個以ramfs為基礎的檔案系統。在新的驅動程式模型被整合進 2.5.1 核心時,ddfs 被改名成driverfs,以更確切描述它的用途。
在2.5核心開發的次年,新的‘驅動程式模型’和‘driverfs’證明了對核心中的其他子系統也有用處。kobjects被開發出來,作為核心物件的中央管理機制,而此時driverfs也被改名成sysfs。
正因為devfs上述這些問題的存在,在linux2.6內核以后,引入了一個新的文件系統sysfs,它掛載於/sys目錄下,跟devfs一樣它也是一個虛擬文件系統,也是用來對系統的設備進行管理的,它把實際連接到系統上的設備和總線組織成一個分級的文件,用戶空間的程序同樣可以利用這些信息以實現和內核的交互。
該文件系統是當前系統上實際設備樹的一個直觀反應,它是通過kobject子系統來建立這個信息的,當一個kobject被創建的時候,對應的文件和目錄也就被創建了,位於/sys下的相關目錄下,既然每個設備在sysfs中都有唯一對應的目錄,那么也就可以被用戶空間讀寫了。用戶空間的工具udev就是利用了sysfs提供的信息來實現所有devfs的功能的,但不同的是udev運行在用戶空間中,而devfs卻運行在內核空間,而且udev不存在devfs那些先天的缺陷。很顯然,sysfs將是未來發展的方向。
內核的結構化設備模型在用戶空間就稱為sysfs.它與procfs類似,二者都位於內存的文件系統中,而且包含內核數據結構的信息。但是,procfs是查看內核內部的一個通用視窗,而sysfs則特定的對應於設備模型。因而,sysfs並非procfs的替代品。進程描述符、sysctl參數等信息屬於procfs而非sysfs。udev的大多數功能都取決於sysfs。
三、udev
udev是一種工具,它能夠根據系統中的硬件設備的狀況動態更新設備文件,包括設備文件的創建,刪除等。設備文件通常放在/dev目錄下,使用udev后,在/dev下面只包含系統中真實存在的設備。它於硬件平台無關的,位於用戶空間,需要內核sysfs和tmpfs的支持,sysfs為udev提供設備入口和uevent通道,tmpfs為udev設備文件提供存放空間。
四、實例sysfs
trace 的程式是 cpufreq,推薦一下這個程式,裡面有完整的 kobject initial、如何套到一個 sys_device 上、ktype的宣告等。裡面也有一些不錯的寫程式技巧,減低了重覆宣告 kyte 的 attribute 和 ops(這些技巧在kernel code中常出現,想必是不錯的撰寫風格),想了解 sysfs 的話,我想 cpufreq 算是不錯的範例格式。
kobject: 最小的 device model unit。單純地宣告一個 kobject 並沒什麼用處,他最神奇的地方是內嵌在 Kernel 的 device 資料結構中,例如 character device(cdev), block device(blkdev)。這些資料結構中都會內嵌一個 kobject.
ktype: kobject 的集合。但它比較偏向收集相同 operation 的 kobject 的一個集合,也就是說它是負責管理這一群 kobjects 的 operation. (show,store)。kobject 會利用它了辨識自已是屬於那一個類型,然後在 /sys 下建立正確的目錄位置。
kset: kobject 的集合。這也是一個集合,不同於ktype,它不管理 kobject 的 ops,最重要的是建立上層(sub-system)和下層的(kobject)的關聯性。kobject 也會利用它了辨識自已是屬於那一個類型,然後在 /sys 下建立正確的目錄位置。而 kset 的優先權比較高,kobject 會利用自已的 *kset 找到自已所屬的kset,並把 *ktype 指定成該kset下的ktype,當然,你也是可以搞鬼,設定了kset,但用不同的ktype的operation(...有些code是這樣)。除非沒有定義kset,才會用 ktype 來建立關聯。
subsystem:如果說 kset 是管理 kobject 的集合,同理、subsystem 就是管理 kset 的集合。
attribute: 建立了 kobject 並成功註冊之後,你會發現出現該 kobj 對應的目錄竟然是空的(這是當然的啦 XD),要如何產生資訊檔案,就是利用 attribute 這個資料結構。
struct attribute {
char *name; // 以該變數為檔名出現在 kobj 的目錄下
struct module *owner; // THIS_MODULE
mode_t mode; //permission, "S_IRUGO" or "S_IWUSR" or "0660"
};
應該是的出來 attribute 的功用,建立好attribute之後,讀取/寫入該檔案會呼叫 ktype 對應的 operation.