概述

LDD3中說:“Linux核心需要一個對系統結構的一般性描述。”這個描述就是linux裝置驅動模型(下面簡稱為LDDM)。LDDM不是獨立存在,其體系如下圖所示:

LDDM體系結構

對架構的每一部分本文都會開闢獨立的章節進行描述。暫且拋開這個架構,首先從總體上了解一下LDDM。

LDDM與驅動程式密切相關,而驅動程式處於linux系統中的什麼位置呢?我們自頂向下一步步來說,先看下圖[以下內容以http://www.wowotech.net/sort/device_model中的內容為主體結合自己的認識和對於4.1核心的修改,這個系列文章非常好,推薦],linux由五個部分組成


1. Process Scheduler,也稱作程序管理、程序排程。負責管理CPU資源,以便讓各個程序可以以儘量公平的方式訪問CPU

2. Memory Manager,記憶體管理。負責管理Memory(記憶體)資源,以便讓各個程序可以安全地共享機器的記憶體資源。另外,記憶體管理會提供虛擬記憶體的機制,該機制可以讓程序使用多於系統可用Memory的記憶體,不用的記憶體會通過檔案系統儲存在外部非易失儲存器中,需要使用的時候,再取回到記憶體中。

3. VFSVirtual File System),虛擬檔案系統。Linux核心將不同功能的外部裝置,例如Disk裝置(硬碟、磁碟、NAND FlashNor Flash等)、輸入輸出裝置、顯示裝置等等,抽象為可以通過統一的檔案操作介面(openclosereadwrite等)來訪問。這就是Linux系統“一切皆是檔案”的體現(其實Linux做的並不徹底,因為CPU、記憶體、網路等還不是檔案,如果真的需要一切皆是檔案)。

4. Network,網路子系統。負責管理系統的網路裝置,並實現多種多樣的網路標準。

5. IPCInter-Process Communication),程序間通訊。IPC不管理任何的硬體,它主要負責Linux系統中程序之間的通訊。

其中與裝置驅動相關的是VFS子系統,VFS子系統包含5個模組:

1. Device Drivers,裝置驅動,用於控制所有的外部裝置及控制器。由於存在大量不能相互相容的硬體裝置(特別是嵌入式產品),所以也有非常多的裝置驅動。因此,Linux核心中將近一半的Source Code都是裝置驅動,大多數的Linux底層工程師(特別是國內的企業)都是在編寫或者維護裝置驅動,而無暇估計其它內容(它們恰恰是Linux核心的精髓所在)。

2. Device Independent Interface, 該模組定義了描述硬體裝置的統一方式(統一裝置模型),所有的裝置驅動都遵守這個定義,可以降低開發的難度。同時可以用一致的形勢向上提供介面。這一層體現了linux裝置驅動模型的核心思想。

3. Logical Systems,每一種檔案系統,都會對應一個Logical System(邏輯檔案系統),它會實現具體的檔案系統邏輯。使用mount命令可以看到。

4. System Independent Interface,該模組負責以統一的介面(塊裝置和字元裝置)表示硬體裝置和邏輯檔案系統,這樣上層軟體就不再關心具體的硬體形態了。

5. System Call Interface,系統呼叫介面,向用戶空間提供訪問檔案系統和硬體裝置的統一的介面。

從圖中可以看出,VFS包含了裝置驅動的大部分內容(網路驅動不屬於“檔案”),裝置無關介面體現的就是linux裝置驅動模型的核心思想。

LDDM核心思想

如前所述,由於Linux支援世界上幾乎所有的、不同功能的硬體裝置(這是Linux的優點),導致Linux核心中有一半的程式碼是裝置驅動,而且隨著硬體的快速升級換代,裝置驅動的程式碼量也在快速增長。為了降低裝置多樣性帶來的Linux驅動開發的複雜度,以及裝置熱拔插處理、電源管理等,Linux核心提出了裝置模型(也稱作Driver Model)的概念。裝置模型將硬體裝置歸納、分類,然後抽象出一套標準的資料結構和介面。驅動的開發,就簡化為對核心所規定的資料結構的填充和實現

因此,Linux裝置驅動模型是一種抽象,為核心建立起統一的裝置模型。其目的是:

提供一個對系統結構的一般性抽象描述。

LDDM跟蹤所有系統所知道的裝置,以便讓LDDM核心程式協調驅動與新裝置之間的關係。

核心使用Linux裝置驅動模型支援如下任務:

1. 電源管理和系統關機

2. 與使用者空間通訊

   sys虛擬檔案系統的實現與裝置模型密切相關,並且向外界展示了它所表述的結構。向用戶空間所提供的系統資訊,以及改變操作引數的介面,都要通過/sys檔案系統實現,即通過裝置模型實現。

3. 熱插拔裝置

   處理與使用者空間進行熱插拔裝置的通訊是通過裝置模型管理的。

4. 裝置型別

   裝置模型包括了對裝置分類的機制,它會在更高的功能層上描述這些裝置,並使得這些裝置對使用者空間可見。尤其是將命名裝置的功能從核心層轉移到使用者層,大大提高了裝置管理的靈活性。

5. 物件生命週期管理

   裝置模型實現一系列機制以處理物件的生命週期、物件之間的關係,以及這些物件在使用者空間中的表示。簡化程式設計人員建立和管理物件的工作。

Linux裝置驅動模型使用一系列抽象(面向物件設計裡的類),提供統一的裝置管理檢視,這些抽象包括:匯流排、類、裝置和裝置驅動。

Bus(匯流排):匯流排是CPU和一個或多個裝置之間資訊互動的通道。而為了方便裝置模型的抽象,所有的裝置都應連線到總線上無論是CPU內部匯流排、虛擬的匯流排還是“platform Bus在計算機中有這樣一類裝置,它們通過各自的裝置控制器,直接和CPU連線,CPU可以通過常規的定址操作訪問它們(或者說訪問它們的控制器)。這種連線方式,並不屬於傳統意義上的匯流排連線。但裝置模型應該具備普適性,因此Linux就虛構了一條Platform Bus,供這些裝置掛靠。

Class(分類):在Linux裝置模型中,Class的概念非常類似面向物件程式設計中的Class(類),它主要是集合具有相似功能或屬性的裝置,這樣就可以抽象出一套可以在多個裝置之間共用的資料結構和介面函式。因而從屬於相同Class的裝置的驅動程式,就不再需要重複定義這些公共資源,直接從Class中繼承即可。

Device(裝置):抽象系統中所有的硬體裝置,描述它的名字、屬性、從屬的Bus、從屬的Class等資訊。

另外,linux驅動模型還有一類抽象,Device Driver(裝置驅動)Linux裝置模型用Driver抽象硬體裝置的驅動程式,它包含裝置初始化、電源管理相關的介面實現。而Linux核心中的驅動開發,基本都圍繞該抽象進行(實現所規定的介面函式)。

上面提到過,Linux核心通過sys檔案系統展示了裝置驅動模型的內在結構,我們通過sys檔案系統來看看上述抽象如何組織在一起,如何有序的管理linux裝置:

可以看到,linux驅動模型是個複雜的體系,包括裝置樹、匯流排樹、類樹,即使一個簡單的系統裝置模型也會包含幾百個節點,但是Linux裝置驅動模型程式碼會處理好這些關係,模型隱藏在互動背後。

綜上所述,Linux裝置驅動模型的核心思想是

 1. Devicestruct device)和Device Driverstruct device_driver)兩個資料結構,分別從“有什麼用”“怎麼用”兩個角度描述硬體裝置。這樣就統一了編寫裝置驅動的格式,使驅動開發從論述題變為填空體,從而簡化了裝置驅動的開發。

2. 同樣使用DeviceDevice Driver兩個資料結構,實現硬體裝置的即插即用(熱拔插)。

Linux核心中,只要任何DeviceDevice Driver具有相同的名字,核心就會執行Device Driver結構中的初始化函式(probe),該函式會初始化裝置,使其為可用狀態。

而對大多數熱拔插裝置而言,它們的Device Driver一直存在核心中。當裝置沒有插入時,其Device結構不存在,因而其Driver也就不執行初始化操作。當裝置插入時,核心會建立一個Device結構(名稱和Driver相同),此時就會觸發Driver的執行。這就是即插即用的概念。

3. 通過"Bus-->Device”型別的樹狀結構解決裝置之間的依賴,而這種依賴在開關機、電源管理等過程中尤為重要。

試想,一個裝置掛載在一條總線上,要啟動這個裝置,必須先啟動它所掛載的匯流排。很顯然,如果系統中裝置非常多、依賴關係非常複雜的時候,無論是核心還是驅動的開發人員,都無力維護這種關係。

而裝置模型中的這種樹狀結構,可以自動處理這種依賴關係。啟動某一個裝置前,核心會檢查該裝置是否依賴其它裝置或者匯流排,如果依賴,則檢查所依賴的物件是否已經啟動,如果沒有,則會先啟動它們,直到啟動該裝置的條件具備為止。而驅動開發人員需要做的,就是在編寫裝置驅動時,告知核心該裝置的依賴關係即可。

4. 使用Class結構,在裝置模型中引入面向物件的概念,這樣可以最大限度地抽象共性,減少驅動開發過程中的重複勞動,降低工作量。