The Linux Kernel Device Model
Patrick Mochel <[email protected]>
Drafted 26 August 2002
Updated 31 January 2006
Overview~~~~~~~~
新的Linux內核驅動模型對之前內核中各種不同的驅動模型進行了統一化的工作. 目的是對bus相關的驅動做一個增強 --- 通過向全局的數據結構中加入數據和方法
之前的驅動模型將其所控制的設備組織爲類似於樹(有時只是一個列表)的結構。對於不同的bus類型來說,並不存在一個統一的模型。
現在的驅動模型提供了一個通用的、統一的數據模型,用以描述bus及掛載與其上的設備。統一的bus模型包括一套適用於所有總線類型的屬性,以及一套回調函數,比如當探測bus上的設備時所用到的函數(probe),關閉總線的函數(shutdown),電源管理的函數,等等.
通用的設備和橋設備(bridge)接口反映了現代計算機的目標:也就是進行無縫的設備即插即用,電源管理以及熱插拔。尤其是,由Intel和Microsoft所定義的ACPI(Advanced Configuration and Power Management Interface)保證了在這樣一套框架下,所有設備在x86兼容系統上的幾乎所有總線上都能工作。當然,並不是每種總線都支持所有的操作,但事實是,幾乎所有的總線支持幾乎所有的操作。
DownstreamAccess~~~~~~~~~~~~~~~~~
通用的數據域已經從各個總線層中被移到了一個公用的數據結構. 這些域仍舊需要保證能被總線層,有時被特定設備的驅動訪問到.
其它的總線層可以參考PCI層的做法.
結構pci_dev 現在是這樣的:
struct pci_dev {
...
struct devicedev; /* Generic device interface */
...
};
請留意結構pci_dev 中的device域是要靜態申請的。這意味着在探測設備是隻能做一次allocation.
還要留意device結構並非一定要在pci_dev結構之前定義。這麼做的目的是促使大家在總線驅動和全局驅動之間做切換時要考慮下到底在做什麼,並防止無意義的、錯誤的數據結構嵌套.
PCI總線層可以訪問device結構中的域。它瞭解pci_dev結構,當然也瞭解device結構。已經變更到現有的驅動模型的那些PCI設備驅動不會也不應該訪問device結構,除非是編譯上的原因.
上述抽象可以防止向新的模型過渡過程中的不必要的麻煩. 如果不是現在這樣設計,如果某個域被改名或移除,其下游的驅動都將崩潰. 另一方面,如果只有總線層(並非設備層)訪問device結構, 那麼只要修改總線層就夠了.
UserInterface~~~~~~~~~~~~~~
由於系統中的所有設備都組織爲一個完整的樹狀結構,向用戶空間導出該樹狀結構也就相對簡單了. 這個任務由虛擬文件系統sysfs實現.
幾乎所有的主流Linux發行版都會自動mount這個文件系統; 可以在mount命令的輸出中看到:
$ mount
...
none on /sys type sysfs (rw,noexec,nosuid,nodev)
...
$
自動mount的工作一般是由/etc/fstab文件中類似於下面的指令完成的:
none /sys sysfs defaults 0 0
在基於Debian的系統中:
none /sys sysfs nodev,noexec,nosuid 0 0
如果未能自動掛載,可以手動:
# mount -t sysfs sysfs /sys
每當有設備被加入到樹中,在/sysfs就會爲其創建相應的目錄. 探測設備過程中任何層都有可能向該目錄寫入數據– 全局層,總線層或設備層.
全局層目前會創建兩個文件- 'name' 和 'power'. 前者只是用來提供設備的名字. 而後者則提供當前的電源狀態,還可以用於設置電源狀態.
總線層在總線上探測設備時也有可能在目錄中爲探測到的設備創建文件. 例如, PCI層會爲每一個PCI設備創建'irq' 和 'resource' 文件.
設備驅動也可能向該目錄導出文件,用來提供設備數據或可調整的接口.
關於sysfs的佈局,可以在本目錄的其它文檔或Documentation/filesystems/sysfs.txt中找到更多信息.