日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

5、Windows驱动开发技术详解笔记(1) 入门基础驱动程序结构

發布時間:2024/8/26 综合教程 32 生活家
生活随笔 收集整理的這篇文章主要介紹了 5、Windows驱动开发技术详解笔记(1) 入门基础驱动程序结构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

NT式

1、Driver.h頭文件中包含了開發NT式驅動所需要的NTDDK.h,此外還定義了幾個標志來指明函數和變量分配在分頁內存還是非分頁內存中。Windows驅動程序的入口函數是DriverEntry函數。WDM式的驅動程序要導入的頭文件是WDM.h。

代碼

 1 #ifdef __cplusplus
2
3 extern "C"
4
5 {
6
7 #endif
8
9 #include <NTDDK.h>
10
11 #ifdef __cplusplus
12
13 }
14
15 #endif
16
17 #define PAGEDCODE code_seg("PAGE")
18
19 #define LOCKEDCODE code_seg()
20
21 #define INITCODE code_seg("INIT")
22
23 #define PAGEDDATA data_seg("PAGE")
24
25 #define LOCKEDDATA data_seg()
26
27 #define INITDATA data_seg("INIT")
28
29 #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
30
31 typedef struct _DEVICE_EXTENSION {
32
33 PDEVICE_OBJECT pDevice;
34
35 UNICODE_STRING ustrDeviceName; //設備名稱
36
37 UNICODE_STRING ustrSymLinkName; //符號鏈接名
38
39 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
40
41 // 函數聲明
42
43 NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
44
45 VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
46
47 NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
48
49 IN PIRP pIrp);

說明:

1)采用C++編程,所以需要用extern "C",因為我們導入的是C的函數的符號表。

2)在驅動中用到的變量或函數都需要指定分配在分頁或非分頁內存中,分頁內存在物理內存不夠的情況下可能會被交換出去,對于一些需要高IRQL的例程絕對不能被交換出頁面,因此它們必須被定義為非分頁內存。

3)DriverEntry需要放在INIT標志的內存中。

2、驅動程序的入口函數


代碼

 1 /************************************************************************
2
3 * 函數名稱:DriverEntry
4
5 * 功能描述:初始化驅動程序,定位和申請硬件資源,創建內核對象
6
7 * 參數列表:
8
9 pDriverObject:從I/O管理器中傳進來的驅動對象
10
11 pRegistryPath:驅動程序在注冊表的中的路徑
12
13 * 返回值:返回初始化驅動狀態
14
15 *************************************************************************/
16
17 #pragma INITCODE
18
19 extern "C" NTSTATUS DriverEntry (
20
21 IN PDRIVER_OBJECT pDriverObject,
22
23 IN PUNICODE_STRING pRegistryPath )
24
25 {
26
27 NTSTATUS status;
28
29 KdPrint(("Enter DriverEntry\n"));
30
31 //注冊其他驅動調用函數入口
32
33 pDriverObject->DriverUnload = HelloDDKUnload;
34
35 pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
36
37 pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
38
39 pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
40
41 pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
42
43 //創建驅動設備對象
44
45 status = CreateDevice(pDriverObject);
46
47 KdPrint(("DriverEntry end\n"));
48
49 return status;
50
51 }

1)猶如控制臺程序需要main、Win32 程序需要WinMain、DLL 程序需要DllMain 一樣,驅動程序也有自己的入口點,即DriverEntry。DriverEntry 需要被加載到INIT 內存區域中,這樣當驅動被卸載后它可以退出內存。

2)DriverEntry 是由內核中的I/O 管理器負責調用的,它有兩個參數DriverObject 和RegistryPath(當然形參的名字可以自己改變)。其中DriverObject 是由I/O管理器傳遞進來的驅動對象,RegistryPath 則指向此驅動負責的注冊表。

3)我們可以看到DriverEntry 首先是定義了一些變量,然后調用IoCreateDevice 創建設備對象,緊接著調用IoCreateSymbolicLink 創建符號鏈接。HelloDDKDispatchRoutine等是驅動程序在向Windows 的I/O 管理器注冊一些回調函數。上面代碼的含義是:當驅動程序將被卸載時自動調用HelloDDKUnload例程;當驅動程序接收到 IRP_MJ_CREATE 時自動調用HelloDDKDispatchRoutine。

現在可以把IRP_MJ_CREATE理解成類似ring3的“消息”,當我們的驅動程序接收到不同的IRP就表明發生了不同的事件,然后我們及時給予處理。

4)KdPrint是宏,用來輸出。類似于MFC中的TRACE。

5)#pragma INITCODE來指明此函數加載到INIT內存函數中。

6)在驅動對象DriverObject 中,有個函數指針數組MajorFunction,它里面的每一個元素都記錄著一個函數的地址對應著相應的IRP,我們可以通過簡單地設置這個數組將IRP 與相應的派遣函數關聯起來。諸如IRP_MJ_CREATE 其實是使用#define 定義的一個宏,比如IRP_MJ_CREATE 實際上就是0x00,而IRP_MJ_CLOSE 則是0x02 等。由于在進入DriverEntry 之前,I/O 管理器會將_IopInvalidDeviceRequest 的地址填滿整個MajorFunction 數組,因此除了我們自行設置過的IRP 之外,其他的IRP 都與系統默認的_IopInvalidDeviceRequest 函數關聯。

3、創建設備例程(函數)


代碼

 1 /************************************************************************
2
3 * 函數名稱:CreateDevice
4
5 * 功能描述:初始化設備對象
6
7 * 參數列表:
8
9 pDriverObject:從I/O管理器中傳進來的驅動對象
10
11 * 返回 值:返回初始化狀態
12
13 *************************************************************************/
14
15 #pragma INITCODE
16
17 NTSTATUS CreateDevice (
18
19 IN PDRIVER_OBJECT pDriverObject)
20
21 {
22
23 NTSTATUS status;
24
25 PDEVICE_OBJECT pDevObj;
26
27 PDEVICE_EXTENSION pDevExt;
28
29 //創建設備名稱
30
31 UNICODE_STRING devName;
32
33 RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
34
35 //創建設備
36
37 status = IoCreateDevice( pDriverObject,
38
39 sizeof(DEVICE_EXTENSION),
40
41 &(UNICODE_STRING)devName,
42
43 FILE_DEVICE_UNKNOWN,
44
45 0, TRUE,
46
47 &pDevObj );
48
49 if (!NT_SUCCESS(status))
50
51 return status;
52
53 pDevObj->Flags |= DO_BUFFERED_IO;
54
55 pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
56
57 pDevExt->pDevice = pDevObj;
58
59 pDevExt->ustrDeviceName = devName;
60
61 //創建符號鏈接
62
63 UNICODE_STRING symLinkName;
64
65 RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
66
67 pDevExt->ustrSymLinkName = symLinkName;
68
69 status = IoCreateSymbolicLink( &symLinkName,&devName );
70
71 if (!NT_SUCCESS(status))
72
73 {
74
75 IoDeleteDevice( pDevObj );
76
77 return status;
78
79 }
80
81 return STATUS_SUCCESS;
82
83 }

******

RtlInitUnicodeString

http://msdn.microsoft.com/en-us/library/ms648420%28VS.85%29.aspx

IoCreateDevice

http://msdn.microsoft.com/en-us/library/ff548397%28VS.85%29.aspx

1),前面我們創建的設備對象雖然有個參數指定了設備名稱,但是這個設備名稱只能在內核態可見,也就說ring3 的應用層程序是看不見它的,因此驅動程序需要向ring3 公布一個符號鏈接,這個鏈接指向真正的設備名稱,而ring3 的應用程序可以通過該符號鏈接找到驅動程序進行通信。實際上我們經常所說的C 盤、D 盤就是一個符號鏈接,它們在內核中的真正設備對象是“\Device\HarddiskVolume1”和“\Device \HarddiskVolume2”。在內核模式下,符號鏈接是以“\??\”( 或“\DosDevices\”)開頭的,如C 盤就是“\??\C:”,

而在用戶模式下,則是以“\\.\”開頭的,如C 盤就是“\\.\C:”。

4、卸載驅動例程


代碼

 1 #pragma PAGEDCODE
2
3 VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
4
5 {
6
7 PDEVICE_OBJECT pNextObj;
8
9 KdPrint(("Enter DriverUnload\n"));
10
11 pNextObj = pDriverObject->DeviceObject;//由驅動對象得到設備對象
12
13 while (pNextObj != NULL)
14
15 {
16
17 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
18
19 pNextObj->DeviceExtension;
20
21 //刪除符號鏈接
22
23 UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
24
25 IoDeleteSymbolicLink(&pLinkName);
26
27 //刪除設備對象
28
29 pNextObj = pNextObj->NextDevice;
30
31 IoDeleteDevice( pDevExt->pDevice );
32
33 }
34
35 }

卸載驅動例程是我們在DriverEntry 中自己定義的,當驅動被卸載時I/O管理器負責調用該例程,它主要做一些掃尾處理的工作。

KdPrint

由于驅動程序工作于內核態,不像控制臺的程序一樣可以使用printf 輸出一些信息,也不像Win32 程序可以通過MessageBox 來彈出一個對話框,它要想輸出一些信息,就需要調用DbgPrint 函數,不過這個函數輸出的信息我們無法直接看到,需要使用一些專門的工具,比如DbgView (KmdManager)等。

有些內容我們只想在調試版輸出,在發行版忽略,因此DDK 中定義了一個宏KdPrint,它在發行版不被編譯,只在調試版才會運行。KdPrint是這樣定義的:

#define KdPrint(_x_) DbgPrint _x_,在使用時最外層要有兩個連續的括號。

5、派遣例程


代碼

 1 /************************************************************************
2
3 * 函數名稱:HelloDDKDispatchRoutine
4
5 * 功能描述:對讀IRP進行處理
6
7 * 參數列表:
8
9 pDevObj:功能設備對象
10
11 pIrp:從IO請求包
12
13 * 返回 值:返回狀態
14
15 *************************************************************************/
16
17 #pragma PAGEDCODE
18
19 NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
20
21 IN PIRP pIrp)
22
23 {
24
25 KdPrint(("Enter HelloDDKDispatchRoutine\n"));
26
27 NTSTATUS status = STATUS_SUCCESS;
28
29 // 完成IRP
30
31 pIrp->IoStatus.Status = status;
32
33 pIrp->IoStatus.Information = 0; // bytes xfered
34
35 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
36
37 KdPrint(("Leave HelloDDKDispatchRoutine\n"));
38
39 return status;
40
41 }

派遣例程是處理IRP的。

編譯

DDK方式

進入相應目錄,Build

Source如下:

TARGETNAME=HelloDDK

TARGETTYPE=DRIVER

TARGETPATH=OBJ //編譯輸出目錄

INCLUDES=$(BASEDIR)\inc;\

$(BASEDIR)\inc\ddk;\

SOURCES=Driver.cpp\

VC方式:參見[1]第一章。

驅動安裝

用DriverStudio中的工具:DriverMonitor。

WDM式驅動

/************************************************************************

* 函數名稱:DriverEntry

* 功能描述:初始化驅動程序,定位和申請硬件資源,創建內核對象

* 參數列表:

pDriverObject:從I/O管理器中傳進來的驅動對象

pRegistryPath:驅動程序在注冊表的中的路徑

* 返回 值:返回初始化驅動狀態

*************************************************************************/

#pragma INITCODE

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,

IN PUNICODE_STRING pRegistryPath)

{

KdPrint(("Enter DriverEntry\n"));

pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice; //相比NT,此回調函數的作用是創建設備對象并由PNP管理器調用。

...

/************************************************************************

* 函數名稱:HelloWDMAddDevice

* 功能描述:添加新設備

* 參數列表:

DriverObject:從I/O管理器中傳進來的驅動對象

PhysicalDeviceObject:從I/O管理器中傳進來的物理設備對象

* 返回 值:返回添加新設備狀態

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,

IN PDEVICE_OBJECT PhysicalDeviceObject)

{

PAGED_CODE();

KdPrint(("Enter HelloWDMAddDevice\n"));

...

PAGED_CODE();//宏,只有check版本中有效,當此例程所在的中斷請求超過APC_LEVEL時,會產生一個斷言。

***

對IRP_MN_REMOVE_DEVICE的處理,類似于NT式驅動中的卸載例程,而在WDM式驅動中,卸載例程幾乎不做處理。

******

Source文件:

TARGETNAME=HelloWDM

TARGETTYPE=DRIVER

DRIVERTYPE=WDM

TARGETPATH=OBJ

INCLUDES=$(BASEDIR)\inc;\

$(BASEDIR)\inc\ddk;\

SOURCES=HelloWDM.cpp\

編譯:

同NT

安裝:

用EzDriverInstall安裝或控制面版中添加硬件。

實際上,常見的Windows 驅動程序是可以分成兩類的:一類是不支持即插即用功能的NT 式驅動程序,另一類是支持即插即用的WDM 式驅動程序。NT 式驅動的安裝是基于服務的,可以通過修改注冊表進行,也可以直接通過服務函數如CreateService 進行安裝;但WDM 式驅動不同,它安裝的時候需要通過編寫一個inf 文件進行控制。除此之外,它們所使用的頭文件也不大相同,例如NT 式驅動往往需要導入一個名為“ntddk.h”的頭文件,而WDM 式驅動需要的卻是“wdm.h”頭文件。我們在學習的過程中所編寫的大多屬于NT 式驅動,除非我們需要自己的設備支持即插即用,才需要考慮編寫
WDM 式驅動程序。

參考

【1】Windows 驅動開發技術詳解

【2】http://msdn.microsoft.com/en-us/library/ff565757%28VS.85%29.aspx

總結

以上是生活随笔為你收集整理的5、Windows驱动开发技术详解笔记(1) 入门基础驱动程序结构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: av片在线观看免费 | 91字幕网| 久久久久久久久久一区二区 | 一级二级av | 中文字幕23页 | 一级aaa毛片 | 国产免费一区二区三区四区五区 | 日韩精品视频观看 | 久久久九九 | 日本一级黄色 | 国产成年无码久久久久毛片 | 欧美日韩激情一区 | 国产精品综合久久 | 国产黄色大片在线观看 | 高清久久 | 一二三在线视频 | 国产精品夜夜夜爽阿娇 | 成 人片 黄 色 大 片 | 成人在线网址 | 国产一区二区在线播放视频 | 男生把女生困困的视频 | 中文字幕人妻丝袜乱一区三区 | 青青久在线 | 亚洲乱熟女一区二区三区小说 | 色哟哟免费在线观看 | 婷婷五月色综合 | 天天看片天天射 | 91免费视| 麻豆福利影院 | 亚洲精品久久久 | 日韩欧美中文字幕精品 | 欧美性大交| 人妻互换 综合 | 51人人看 | 亚洲综合一区在线 | 9999精品视频 | 午夜视频入口 | 在线播放一区 | 成人h动漫精品一区二区无码 | 国产精品扒开腿做爽爽 | 高清在线一区二区 | 色婷婷av一区二区三区软件 | 天天操天天干天天舔 | 日韩成人黄色片 | 亚洲暴爽 | 欧美精品免费播放 | 精品伦理一区二区 | 樱桃成人精品视频在线播放 | 超碰人人草 | 91蜜桃视频在线观看 | 99精品成人 | 激情吧 | 韩国一二三区 | 欧美色图片区 | 九九超碰| 日本人极品人妖高潮 | 麻豆com| 国产免费一区二区三区最新不卡 | 美女国产精品 | 一区二区三区四区国产 | 亚洲无码乱码精品国产 | 久操视频在线观看 | 色中文字幕在线观看 | 久久免费视频网站 | 人人草人人看 | 快色污 | 明日花绮罗高潮无打码 | 免费h片网站 | 午夜影院在线 | 国精产品一区一区三区视频 | 午夜精品久久久久久99热 | 91性高潮久久久久久久久 | 97人妻精品一区二区三区免 | 亚洲影音| 久草蜜桃 | 精品亚洲国产成人av制服丝袜 | a黄色片| 欧美精品一二三四区 | 欧美成年人视频在线观看 | 东京干手机福利视频 | 激情视频91| 精品国产免费观看 | 中文字幕一区二区三区免费 | av自拍网| a级片免费在线观看 | 欧美三日本三级少妇三级99观看视频 | 亚洲精品一区二区三区中文字幕 | 成人国产精品蜜柚视频 | 高清av免费| 伊人久久激情 | 久久国产露脸精品国产 | 海量av资源 | 亚洲毛片大全 | 狠狠人妻久久久久久综合蜜桃 | 色97| 久久人妻免费视频 | 亚洲女人天堂色在线7777 | 人人模人人干 | 国产精品a久久久久 |