標籤:windows 7
Windows驅動開發基礎:驅動程式的資料結構。轉載請標明出處:http://blog.csdn.net/ikerpeng/article/details/38794405
I/O管理器定義了一些資料結構,這些很重要。
1. 驅動對象(DRIVER_OBJECT)
通過一個typedef 定義的以一個struct:
<span style="font-family:Microsoft YaHei;">typedef struct{PDEVICE_OBJECT DeviceObject; //指向驅動程式建立的裝置對象</span>
<span style="font-family:Microsoft YaHei;">UNICODE_STRING Drivername // 驅動名稱PUNICODE_STRING HardwareDatabase; //記錄的是裝置的硬體資料庫名,這裡同樣用Unicode字串記錄PFAST_IO_DISPATCH FastIoDispatch;//檔案驅動中用到的派遣函數PDRIVER_INITIALIZE DriverInit;//指向DriverEntry函數的,這是通過IO管理器來建立的。PDRIVER_STARTIO DriverStartIo;//記錄StartIO常式的函數地址,用於序列化操作PDRIVER_UNLOAD DriverUnload;//指定驅動卸載時所用的回呼函數地址PDRIVER_DISPATCH MajorFunction[IRP_MJ_NUM+1];//指向驅動程式的DispatchXXX函數指標的數組}DRIVER_OBJECT,*PDRIVER_OBJECT;指向驅動程式的DispatchXXX函數指標的數組</span>
裡面有一些重要的資料結構:
DeviceObject: 裝置對象,可能是一個或多個。由程式猿自己建立,驅動程式被卸載的時候,遍曆每一個DriverObject並刪除;
DeviceName:裝置名稱,儲存在Unicode字串裡面
HardwareDatabase:
HardwareDatabase記錄的是裝置的硬體資料庫名,這裡同樣用Unicode字串記錄。該字串一般為HKEY_LOCAL_MACHINE\Hardware\DESCRIPTION\System,是一個註冊表路徑。
FastIoDispatch:
檔案驅動中用到的派遣函數。指向這個驅動程式的FastIO進入點定義的一個結構。這個成員只能通過FSDs和網路傳輸驅動來使用。
DriverInit:
指向DriverEntry函數的,這是通過IO管理器來建立的。
DriverStartIo:
記錄StartIO常式的函數地址,用於序列化操作,如果一個驅動程式沒有StartIo函數,這個成員將是NULL。
DriverUnload:
指定驅動卸載時所用的回呼函數地址,如果驅動程式沒有卸載函數,這個成員將是NULL。
MajorFunction[IRP_MJ_NUM+1]:
指向驅動程式的DispatchXXX函數指標的數組。每個驅動程式至少要設定一個DispatchXXX函數指標在這個數組裡來處理這個驅動程式IRP請求包。任何一個驅動程式可以設定和IRP_MJ_XXX代碼一樣多的DispatchXXX來處理IRP請求包.每個DispatchXXX結構如下:
NTSTATUS DispatchXXX(IN PDEVICE_OBJECT DeviceObjec, IN PIRP Irp);
2. 裝置對象(DeviceObject):
一張圖理一下裡面的成員的關係:
每個驅動都會有裝置對象,每一個裝置對象都有一個指標指向下一個裝置對象(最後一個為空白)。結構體定義如下:
<span style="font-family:Microsoft YaHei;">typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT{ CSHORT Type; USHORT Size; LONG ReferenceCount; /*指向驅動程式中驅動對象的指標*/ struct _DRIVER_OBJECT *DriverObject; /*指向下一個裝置對象的指標*/ struct _DEVICE_OBJECT *NextDevice; struct _DEVICE_OBJECT *AttachedDevice; /*當前IRP結構*/ struct _IRP *CurrentIrp; PIO_TIMER Timer; /*裝置對象的特性標誌*/ ULONG Flags; ULONG Characteristics; _volatile PVPB Vpb; /*指向裝置擴充項物件的指標*/ PVOID DeviceExtension; /*指明裝置類型*/ DEVICE_TYPE DeviceType; /*堆棧的最小層數*/ CCHAR StackSize; union { LIST_ENTRY ListEntry; WAIT_CONTEXT_BLOCK Wcb; } Queue; /*記憶體對齊*/ ULONG AlignmentRequirement; KDEVICE_QUEUE DeviceQueue; KDPC Dpc; /* *下列成員用於支援檔案系統的互斥操作 *以便對檔案系統處理線程使用裝置的計數保持跟蹤 */ ULONG ActiveThreadCount; PSECURITY_DESCRIPTOR SecurityDescriptor; KEVENT DeviceLock; USHORT SectorSize; USHORT Spare1; struct _DEVOBJ_EXTENSION *DeviceObjectExtension; PVOID Reserved; } DEVICE_OBJECT;typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT;</span>
下面分別描述裝置對象中驅動程式可訪問成員的具體含義:
PDRIVER_OBJECT DriverObject:指向驅動程式中的驅動對象。同屬一個驅動程式的驅動對象指標都指向同一個驅動對象。
PDEVICE_OBJECT NextDevice:指向下一個裝置對象。這裡的下一個裝置對象是同一個驅動程式建立的若干裝置對象中的一個。每個裝置對象會根據
NextDevice成員形成鏈表,從而遍曆每個裝置對象。在每次成功調用IoCreateDevice 後,I/O管理器就會更新該鏈表。當驅動被卸載時,需要遍曆該鏈表,刪除每個裝置對象。
PIRP CurrentIrp:如果驅動使用StartIO常式,此成員將指向當前的IRP結構,否則為NULL。
ULONG Flags:此成員是一個32位的無符號整型變數,每個位有不同的含義。可通過按位取“或”操作為新建立的裝置對象設定不同的特性。
ULONG Characteristics:此成員說明裝置對象的特性,當驅動程式調用IoCreate-Device時,可設定FILE_REMOVABLE_MEDIA(表示存放裝置支援可移動介質)、FILE_READ_ONLY_DEVICE(表示裝置不能寫)、FILE_FLOPPY_DISKETTE(表示裝置是磁碟片裝置)等值。
PVOID DeviceExtension:指向裝置擴充項物件。
DEVICE_TYPE DeviceType:指明裝置的類型,由IoCreateDevice設定,根據裝置的需要填寫相應的裝置類型。
CCHAR StackSize:在多層驅動的情況下,驅動與驅動之間形成類似堆棧的結構。IRP會依次從最高層傳遞到最底層。StackSize就是用於指定發送到該驅動的IRP在堆棧位置的最小層數的。IoCreateDevice在一個新建立的裝置對象中設定該成員。
ULONG AlignmentRequirement:進行資料轉送的時候,規範裝置的地址對齊
其中的DeviceType:指明裝置的類型,當作為一個虛擬裝置的時候選擇:FILE_DEVICE_UNKNOWN.
3. 裝置擴充:
裝置對象記錄的是通用的資訊,而一些特殊的資訊則要記錄於裝置擴充裡面了。
在驅動程式裡面最好不要使用全域變數,這往往導致函數的不可重新進入性。將全域變數以裝置擴充的形式儲存,並加以保護措施,這樣可以解決這個問題。
參考文獻:
《Windows驅動開發技術詳解》
http://www.cnblogs.com/qintangtao/archive/2013/04/09/3009790.html
Windows驅動開發基礎(五)驅動程式的資料結構