1. 程式人生 > >Windows驅動開發WDM (1)

Windows驅動開發WDM (1)

驅動物件(DRIVER_OBJECT)

每個驅動程式會有唯一的驅動物件與之對應,並且這個驅動物件是在驅動載入的時候,被核心中的物件管理程式所建立的。

說明一下其中的一個成員:DeviceObject。

MSDN上面是這麼定義:

PDEVICE_OBJECT DeviceObject

Pointer to the device objects created by the driver. This member is automatically updated when the driver callsIoCreateDevice successfully. A driver can use this member and theNextDevice

 member ofDEVICE_OBJECT to step through a list of all the device objects that the driver created.

DeviceObject指向驅動物件的第一個裝置物件。DeviceObject->NextDevice指向下一個裝置物件,最後一個裝置物件的NextDevice指向空。比如第一次呼叫IoCreateDevice的時候,DriverObject->DeviceObject指向第一個裝置物件(DeviceObject->NextDevice=NULL),再呼叫一次IoCreateDevice建立第二個裝置成功後,DriverObject->DeviceObject->NextDevice會指向第二個裝置物件。

裝置物件都是由驅動程式建立的,而非作業系統建立,當驅動被解除安裝的時候,需要遍歷每個裝置物件,並將其刪除。

裝置物件(DEVICE_OBJECT)

每個驅動會建立一個或者多個裝置物件,用DEVICE_OBJECT表示。每個裝置物件都有一個指標指向下一個裝置物件,因此形成一個裝置鏈。裝置鏈的第一個裝置是由DRIVER_OBJECT的DeviceObject指定。

需要說明的是:

1. NextDevice,指向下一個裝置物件,注意這裡指的下一個物件是同屬於一個驅動物件的裝置。也就是說這個裝置鏈是指同一個驅動物件的裝置鏈。

2. AttachedDevice,這裡指的是更高一層驅動的裝置物件。比如另外一個驅動附加到本驅動,那麼AttachedDevice指的是那個驅動裡面的第一個裝置物件。

裝置擴充套件 (DEVICE_EXTENSION)

DEVICE_OBJECT裡面記錄一些通用資訊,但是大多數情況下,驅動程式需要額外記錄一些資訊,這個時候就需要裝置擴充套件了。

裝置擴充套件是由程式設計師指定內容和大小,由I/O管理器建立的,並且儲存在非分頁記憶體中

在驅動程式中,儘量不要使用全域性變數,資料可以儲存在裝置擴充套件裡面。

WDM驅動的基本結構

從Windows2000以後,微軟引入了新的驅動模型:WDM。WDM是建立在NT驅動模型之上的。

WDM驅動一般分為2種裝置物件:

1. 物理裝置物件(Physical Device Object,PDO)

2. 功能裝置物件(Function Device Object,FDO)

比如:當用戶插入USB盤的時候,匯流排驅動會建立PDO,然後提示使用者載入FDO,如果作業系統已經提供了相應的驅動,那麼作業系統會自動載入這個驅動。如果沒有,則需要使用者去安裝相應的驅動。

在FDO和PDO之間,可以建立過濾驅動。

1. 位於FDO下面的,稱之為下層過濾驅動;

2. 位於FDO上面的,稱之為上層過濾驅動。

簡單畫了一個示意圖:

過濾驅動不是必須的,在WDM中,基本上可以說PDO和FDO是必須的。AttachedDevice指向上層驅動的裝置物件。

入口程式DriverEntry

跟NT驅動一樣,WDM驅動的入口函式也是DriverEntry。WDM驅動需要額外設定2個派遣函式:

1. AddDevice

2. IRP_MJ_PNP

跟NT驅動不同,NT驅動一旦載入就建立裝置,而WDM驅動是作業系統載入PDO以後,呼叫驅動的AddDevice例程,然後在AddDevice例程裡面建立FDO,並且附加到PDO之上。

驅動程式的垂直層次結構

DeviceObject->AttachedDevice指向上層裝置,如上面的圖示。但是裝置物件裡面不能記錄下一層驅動的裝置物件(NextDevice指的是同一個驅動裡面的下一個裝置物件),這時就可以通過裝置擴充套件來記錄。

通過AttachedDevice和裝置擴充套件,我們可以遍歷整個裝置物件堆疊,包括從上到下和從下到上。

驅動程式的水平層次結構

《windows驅動技術開發詳解》裡面將同一個驅動創建出來的裝置物件的關係稱之為水平層次,我覺得還是蠻形象的。

水平層次的第一個裝置物件是由它的驅動物件所指定(DRIVER_OBJECT::DeviceObject)。每一個裝置物件可以通過NextDevice找到水平層次(同一個驅動物件)的下一個裝置物件。

比如插入2塊同樣型號的網絡卡。插入第一個網絡卡的時候,系統會建立一個PDO,並且載入相應的FDO,插入第二個網絡卡的時候,系統建立另外一個PDO,並且載入相應的FDO。那麼這兩個PDO之間就是同一個水平層次,這兩個FDO也處於同一個水平層次。