Download - Windows 环境下的程序设计
![Page 1: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/1.jpg)
WindowsWindows 环境下的程序设计环境下的程序设计Instructor: Hengming Zou, Ph.D.
In Pursuit of Absolute Simplicity 求于至简,归于永恒
![Page 2: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/2.jpg)
22
Windows环境下的程序设计
1. Windows 应用程序设计模式 2. 结构化异常处理 3. 动态链接库 4. Windows驱动程序模型 5. WDM驱动程序编程实例 6. 开发 WDM驱动程序的一般方法
![Page 3: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/3.jpg)
33
Windows 应用程序设计模式
Windows 应用程序是特意为在 Windows 环境中运行而编写的应用程序
以窗口为核心的用户界面、以事件驱动为动力的程序运行机制、以及将程序代码与用户界面分开处理的程序开发手段,构成了 Windows应用程序特有的设计模式
![Page 4: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/4.jpg)
44
Win32 API
Windows 应用程序总是在常规的用户态下运行 操作系统核心组件则对外界表现出中立的性质,它们不实现
用户界面,甚至不提供编程接口,系统服务调用对应用程序而言是不公开的
Windows操作系统依靠一组用户态环境子系统,作为应用程序与操作系统核心之间的接口
![Page 5: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/5.jpg)
55
Win32 API
Win32子系统是 Windows 操作系统的固有的子系统,这个子系统能够提供应用程序运行所需要的窗口管理、图形设备接口、媒体控制、内存管理等各项服务功能,这些功能以函数库的形式组织在一起,这就是 Win32应用程序编程接口,简称为 Win32 API
Win32子系统负责将 API调用转换成 Windows操作系统的系统服务调用
![Page 6: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/6.jpg)
66
Win32 API
Windows 应用程序与操作系统的关系
Windows应用程序
Win32子系统
子系统 用户态
核心态系统服务
Windows应用程序
硬件层
![Page 7: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/7.jpg)
77
Win32 API
USER32.DLL:负责处理用户接口 GDI32.DLL:负责在图形设备上执行绘图操作 KERNEL32.DLL:操作系统核心功能服务 COMCTL32.DLL:通用控件库 COMDLG32.DLL:公共对话框 SHELL32.DLL:用户界面外壳 DIBENG.DLL:图形引擎 NETAPI32.DLL:网络
![Page 8: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/8.jpg)
88
Win32 API
标准 Win32 API函数分类:– 系统服务– 通用控件库– 图形设备接口– 网络服务– 用户接口– 系统 Shell
– Windows 系统信息
![Page 9: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/9.jpg)
99
Windows应用程序设计模式
窗口 目的是保证用户能够同时访问大多数应用程序 应用程序使用窗口来显示输出或接收用户的输入 应用程序只有通过窗口才能访问系统显示器;并且通过使用
窗口与其他应用程序共享系统显示器
![Page 10: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/10.jpg)
1010
Windows应用程序设计模式
事件驱动 Windows 应用程序的执行顺序取决于事件发生的顺序,描
述事件发生的信息称为消息,而事件驱动程序设计则是围绕着消息的产生与处理而展开的
消息可以分为由硬件设备产生的输入消息和来自 Windows系统的窗口管理消息
发送消息—— send
指派消息—— post
![Page 11: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/11.jpg)
1111
Windows应用程序设计模式
事件驱动
硬件输入 系统消息队列
应用程序队列 1
应用程序队列n
Windows
WinMain函数消息循环
窗口函数1
窗口函数m
应用程序1
WinMain函数消息循环
应用程序n
窗口函数1
窗口函数m
![Page 12: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/12.jpg)
1212
Windows应用程序设计模式
Windows应用程序的开发流程 Windows 应用程序分为程序代码和用户界面资源两部分,
两部分通过资源编译器组合为一个完整的 EXE文件 将用户界面资源一类的静态数据与程序代码相分离有如下一
些优点 :– 减少内存要求;– 划清了程序员与用户界面设计人员的任务分工– 用户界面风格的变化可以不必修改程序代码或只需进行少量的修改
![Page 13: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/13.jpg)
1313
Windows应用程序设计模式
Windows应用程序的开发流程
.C .H .RC
.DEF
.DLG
.EXE链接器.LIB
.
. .BMP .CUR.ICO .FON
.RES
.OBJ
资源编译器
C 编译器
字体编辑器图象编辑器对话框编辑器
工具
文本文件
二进制文件
![Page 14: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/14.jpg)
1414
Windows应用程序的基本结构
Windows应用程序具有相对固定的基本结构,入口点函数WinMain和窗口函数构成了 Windows应用程序的基本框架
![Page 15: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/15.jpg)
1515
Windows应用程序的基本结构
WinMain函数– 是程序的入口点,相当于标准 C 语言中的 main函数
WinMain函数主要由四部分组成:– 注册窗口类– 创建窗口– 显示窗口– 建立消息循环
![Page 16: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/16.jpg)
1616
Windows应用程序的基本结构
WinMain函数消息循环 Windows并不直接把输入消息发送给应用程序,而是将其送
入应用程序的消息队列之中。此外, Windows和其他应用程序也可以将消息指派到应用程序队列中
应用程序必须读取应用程序队列,检索消息并将它们发送出去,以便适当的窗口函数能够处理它们,负责这一任务的便是消息循环
![Page 17: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/17.jpg)
1717
Windows应用程序的基本结构
WinMain函数消息循环– while(GetMessage(&Msg, NULL, 0,0))
– {
– TranslateMessage(&Msg);
– DispatchMessage(&Msg);
– }
GetMessage函数检索到 WM_QUIT消息时返回非零值,检索到其他消息均返回
![Page 18: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/18.jpg)
1818
Windows应用程序的基本结构
窗口函数 窗口函数也称为窗口过程,负责从 Windows接收消息,并根
据这些消息完成特定的操作 窗口函数是一个回调函数,由 Windows系统调用,应用程序
并不会直接调用它的窗口函数 窗口函数的主体是由一系列 case语句组成的消息处理程序
段 如果窗口函数不处理某些消息,则必须把它们传给DefWindowProc函数
![Page 19: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/19.jpg)
case 1
case 2
case 3
…
Default
Windows 系统
应用程序WinMain( )
消息循环
WndProc( )
④DispatchMessage( )
⑥
⑤
DefWindowProc( )
检索到的消息③
GetMessage( )②
指派的消息
WM_KEYDOWNWM_KEYUPWM_MOUSEMOVEWM_LBUTTONDOWNWM_QUIT…...
发送的消息
WM_CREATEWM_DESTROYWM_SIZEWM_PAINT…...
①
应用程序的消息队列
回调
Windows应用程序的消息处理过程
![Page 20: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/20.jpg)
2020
Windows应用程序的基本结构
当用户关闭窗口时, Windows系统将把 WM_DESTROY消息发送给该窗口的窗口函数,在这种情况下,窗口函数应该使用 PostQuitMessage函数将 WM_QUIT消息发送到应用程序队列中,这样可以使 GetMessage函数检索到 WM_QUIT消息,从而结束消息循环,退出应用程序
![Page 21: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/21.jpg)
case 1
case 2
...
case WM_DESTROY
Default
Windows 系统
应用程序WinMain( )
消息循环
WndProc( )
②
PostQuitMessage (0)
WM_QUIT消息⑤
GetMessage ( )④
WM_QUIT消息
应用程序的消息队列
WM_DESTROY消息
①
③
退出消息循环结束应用程序
⑥
WM_DESTROY
消息的处理过程
![Page 22: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/22.jpg)
2222
结构化异常处理
Windows在系统底层提供了一种称为结构化异常处理 SEH的系统机制。利用 SEH可以把程序主要的工作同错误处理分离开来,这样的分离,可以使程序员集中精力关注程序要完成的任务,而将可能发生的错误放在后面处理
异常是在应用程序的正常执行过程中发生的不正常事件。 CPU引发的异常称为硬件异常,操作系统和应用程序直接引发的异常,称为软件异常
![Page 23: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/23.jpg)
2323
结构化异常处理
SHE是操作系统的一种系统机制,与特定的程序设计语言无关
应用程序要利用系统提供的 SHE机制,则必须借助于特定程序设计语言的相关语法
因此, SEH不但涉及操作系统,而且与编译器有密切的关系 结构化异常处理包括异常处理和终止处理两个方面
![Page 24: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/24.jpg)
2424
结构化异常处理
异常处理– __try
– {
– ... //guarded section
– }
– __except(exception filter)
– {
– ... //exception handler
– }
![Page 25: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/25.jpg)
2525
结构化异常处理
异常处理 异常过滤器返回如下三个异常标识符之一
– ECXEPTION_EXECUTE_HANDLER
– ECXEPTION_CONTINUE_EXECUTION
– ECXEPTION_CONTINUE_SEARCH
![Page 26: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/26.jpg)
2626
结构化异常处理
终止处理 Windows应用程序在运行时通常要分配资源,使用这些资源,然后释放它们
由于异常改变了控制的流程,因此很容易导致无法释放在产生异常的代码块中分配的资源
使用终止处理程序可以保证进行这样的清除工作
![Page 27: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/27.jpg)
2727
结构化异常处理
终止处理– __try
– {
– ...
– }
– __finally
– {
– ...
– }
![Page 28: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/28.jpg)
2828
结构化异常处理
终止处理 有两种情况可能使受保护段不正常地结束
– 在 try块中执行了 return、 goto、 break或 continue等控制语句
– 在 try块中发生异常
![Page 29: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/29.jpg)
2929
结构化异常处理
软件异常 当一个函数执行失败时,习惯上要返回一些特殊的值来,函
数的调用者可以检查这些特殊值并采取一种替代的动作 如果这个调用者是被另一个调用者调用的函数,那么它还需
要将它自己的失败代码返回给它的调用者 这种错误代码的逐层传递会使源程序变得非常难于编写和维护
采用软件异常则可以解决这些问题
![Page 30: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/30.jpg)
3030
动态链接库
动态链接库 DLL是一个可执行程序模块,模块中包含了可以被其他应用程序或其他 DLL共享的程序代码和资源
![Page 31: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/31.jpg)
3131
动态链接库
采用 DLL的优点:– 当多个进程同时使用同一个 DLL时,只要在内存中装入它的一
个副本即可,从而可以节省内存;– DLL与调用它的应用程序相分离,因此可以在不修改应用程序
的情况下对 DLL进行更新;– 只要在调用 DLL中的函数时遵循相同的调用规范,那么 DLL
中的函数就可以被各种编程语言编制的应用程序调用
![Page 32: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/32.jpg)
3232
动态链接库
DLL到进程地址空间的映射– 装入时刻动态链接
经过编译的.obj文件 引入库,包含DLL函数的重定位信息
链接器
可执行程序
重定位信息
动态链接库
调用DLL中的函数内存
![Page 33: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/33.jpg)
3333
动态链接库
DLL到进程地址空间的映射– 运行时刻动态链接– 在运行时刻,通过调用 LoadLibrary可以使 DLL加载到一个进程的地址空间中
– 为了在运行时刻从 DLL中调用一个函数,可以通过调用GetProcAddress获取函数的地址
![Page 34: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/34.jpg)
3434
动态链接库
DLL到进程地址空间的映射
虚拟地址空间
0
2GB
0
2GB
进程1 进程2
DLL数据(共享)
DLL数据(私用进程1)
DLL数据(私用进程1)
DLL代码
物理内存
![Page 35: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/35.jpg)
3535
动态链接库
DLL的入口点函数 DLL没有 WinMain函数,不含有消息循环,一般也不获取自己的消息,但是它有自己特殊的入口点函数,入口点函数的缺省名为 DllMain
当进程和线程被初始化或终止时, DllMain函数被Windows系统调用
DllMain要做的主要任务是执行进程级或线程级的初始化和清理工作
如果不要求 DLL初始化, DllMain可以只是一个虚设函数
![Page 36: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/36.jpg)
3636
动态链接库
DLL的创建和使用 创建 DLL文件需要用到源文件( .C)和头文件
( .H)。 DLL源文件通常包括入口点函数和供应用程序调用的 DLL库函数。头文件中含有 DLL要导出的所有函数与变量的说明
在应用程序中调用 DLL中的函数或访问 DLL中的变量时,须告诉编译器要调用的函数或要访问的变量是在 DLL中:– __declspec(dllimport)
– int Sub(int nPara1, int Para2);
![Page 37: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/37.jpg)
3737
习题
Win32子系统与 Win32 API的关系是什么? 什么是事件驱动? Windows应用程序为什么采用事件驱动的
程序设计方法,而不是象传统 DOS应用程序那样采用过程驱动的程序设计方法?
与静态链接相比,动态链接有哪些优点?有哪些缺点?
![Page 38: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/38.jpg)
3838
Windows驱动程序模型
WDM以 Windows NT 4.0的内部结构为基础,同时引入了 Windows 9x的即插即用特性,为存在于 Windows 98和Windows 2000/XP/2003操作系统中的设备驱动程序提供了一个统一的参考框架
WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非 Intel平台上运行,因此 WDM是一个跨平台的驱动程序模型
![Page 39: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/39.jpg)
3939
设备和驱动程序的分层
WDM是一个分层化的驱动程序模型,在这个模型中,驱动程序的层或堆栈一起工作处理 I/O请求
FiDO
FDO
FiDO
PDO
上层过滤器驱动程序
功能驱动程序
下层过滤器驱动程序
总线驱动程序
IRP
![Page 40: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/40.jpg)
4040
设备和驱动程序的分层
总线驱动程序 总线驱动程序负责枚举连接在该总线上的所有设备并进行必
要处理 Microsoft为大多数总线如 PCI、 PnPISA、 SCSI以及USB等提供了驱动程序
机器中每种类型的总线都有相应的总线驱动程序 总线枚举时驱动程序识别其上的设备并为其创建一个物理设
备对象
![Page 41: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/41.jpg)
4141
设备和驱动程序的分层
功能驱动程序 功能驱动程序是一个设备的主要驱动程序,它知道如何控制
设备的主要功能 功能驱动程序为它的设备提供操作接口,处理对设备的读 /
写,并管理设备的电源策略 功能驱动程序创建一个功能设备对象 FDO放在设备栈中
![Page 42: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/42.jpg)
4242
设备和驱动程序的分层
过滤器驱动程序 过滤器驱动程序过滤对每个设备、每一类设备或一条总线的I/O请求
过滤器驱动程序是可选择的
![Page 43: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/43.jpg)
4343
IRP的处理
IRP是驱动程序操作的中心。 I/O管理器接收一个 I/O请求之后,在把它传递到合适的驱动程序堆栈中的最高层驱动程序之前,分配并初始化一个 IRP
当一个 IRP由多个驱动程序处理时,使用多个 I/O堆栈单元。每个驱动程序从当前 I/O堆栈单元得到它的 IRP参数。如果把一个 IRP沿当前设备的驱动程序堆栈向下传递,必须使用正确的常数设置下一个堆栈单元
![Page 44: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/44.jpg)
4444
IRP的处理
驱动程序1
驱动程序2
驱动程序3
驱动程序4
I/O堆栈单元 1
I/O堆栈单元 2
I/O堆栈单元 3
I/O堆栈单元 4
IRP
最低
最高
![Page 45: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/45.jpg)
4545
用户程序对设备的访问过程
Windows中对设备的访问分为用户态和核心态两种方式:– 用户态通过调用 Win32 API函数如ReadFile、 WriteFile等访问设备,它不能直接控制硬件
– 核心态通过发送 I/O请求包 IRP来运行驱动程序实现对设备的控制
![Page 46: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/46.jpg)
4646
用户程序对设备的访问过程
应用程序
Win32子系统 用户态
核心态I/O系统服务
I/O管
理器
IRP 高层驱动程序
中层驱动程序
低层驱动程序
HAL
![Page 47: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/47.jpg)
4747
WDM驱动程序的结构
分发例程I/O控制例程
StartIo
AdapterControl
OnInterrupt
DpcForIsr
DriverEntry
AddDevice
基本驱动程序例程
必须的驱动程序例程处理请求队列需要包含StarIo如果设备产生中断需要包含中断和DPC例程DMA 操作需要包含AdapterControl例程可选的IRP分发例程
DispatchPnp
DispatchPower
DispatchWmi
DispatchRead
DispatchWrite
![Page 48: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/48.jpg)
4848
WDM驱动程序的结构
初始化例程,当 I/O管理器把驱动程序加载到操作系统中时,它执行驱动程序的初始化例程
添加设备例程,用于支持 PnP管理器的操作 一系列分发 ( 调度 ) 例程,调度例程是设备驱动程序提供的
主要函数 启动 I/O例程,驱动程序可以使用启动 I/O例程来初始化与
设备之间的数据传输
![Page 49: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/49.jpg)
4949
WDM驱动程序的结构
中断服务例程( ISR),当一个设备中断时,内核的中断调度程序把控制转交给这个例程。 ISR运行在高级的设备中断请求级( IRQL)上,越简单越好,以避免对低优先级中断产生不希望的阻塞
中断服务 DPC例程, DPC例程执行在 ISR执行以后的大部分设备中断处理工作。 DPC例程在低于 ISR的 IRQ的时候执行,从而避免对其他中断产生不希望的阻塞。 DPC例程初始化I/O完成并启动关于设备的下一个队列的 I/O操作
![Page 50: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/50.jpg)
5050
WDM驱动程序编程实例
WdmDriver是一个 WDM驱动程序,它实现了一个 4 字节的核心态内存缓冲区, Win32 应用程序可以对该缓冲区进行读写操作
由于采用 WDM模型, WdmDriver 可以运行在 Windows 98 和 Windows 2000/XP/2003两个平台上
![Page 51: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/51.jpg)
5151
DriverEntry例程
驱动程序向 I/O管理器显露一个名为 DriverEntry的函数,在启动驱动程序的时候, I/O管理器将调用这个入口函数。 DriverEntry相当于作为应用程序入口的 main函数或WinMain函数
驱动程序可以被多个类似的硬件使用,但驱动程序的某些全局初始化操作只能在第一次被装入时执行一次, DriverEntry例程就是用于这个目的
DriverEntry例程的主要工作是把各种函数指针填入驱动程序对象,这些指针为操作系统指明了驱动程序容器中各种子例程的位置
![Page 52: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/52.jpg)
5252
DriverEntry例程extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->DriverStartIo = StartIo;
DriverObject->MajorFunction[IRP_MJ_PNP]=DispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
...
servkey.Buffer = (PWSTR) ExAllocatePool(PagedPool,
RegistryPath->Length + sizeof(WCHAR));
if (!servkey.Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
servkey.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
RtlCopyUnicodeString(&servkey, RegistryPath);
return STATUS_SUCCESS;
}
![Page 53: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/53.jpg)
5353
AddDevice例程
AddDevice函数的基本职责是创建一个设备对象并把它连接到以 pdo为栈底的设备堆栈中,主要步骤如下:– 调用 IoCreateDevice创建设备对象,并建立一个私有的设
备扩展对象 – 注册一个或多个设备接口,以便应用程序能知道设备的存在。另外,还可以给出设备名并创建符号连接
– 调用 IoAttachDeviceToDeviceStack函数,把新设备对象放到堆栈上
– 初始化设备对象的 Flag成员
![Page 54: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/54.jpg)
5454
AddDevice例程
1 .创建设备对象与设备扩展对象 :PDEVICE_OBJECT fdo;
NTSTATUS status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&fdo);
if (!NT_SUCCESS(status))
return status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
pdx->DeviceObject = fdo;
pdx->Pdo = pdo;
![Page 55: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/55.jpg)
5555
AddDevice例程
2 .注册设备接口...
status = IoRegisterDeviceInterface(pdo,
&GUID_SIMPLE,
NULL,
&pdx->ifname);
...
if(!NT_SUCCESS(status))
{
IoDeleteDevice(fdo);
return status;
}
![Page 56: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/56.jpg)
5656
AddDevice例程
3 .建立设备堆栈
...
pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
...
if(!pdx->LowerDeviceObject)
{
IoDeleteDevice(fdo);
return STATUS_DEVICE_REMOVED;
}
![Page 57: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/57.jpg)
5757
AddDevice例程
4 .设置设备标志
fdo ->Flags |= DO_BUFFERED_IO; fdo ->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
![Page 58: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/58.jpg)
5858
其他必须的例程
DispatchPnp例程 DispatchPower例程 DispatchWmi例程
![Page 59: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/59.jpg)
5959
DispatchPnp例程NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
{
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG fcn = stack->MinorFunction;
NTSTATUS status = StaTUS_SUCCESS;
Switch(fcn)
{
case IRP_MN_START_DEVICE:
status = PnpStartDeviceHandler(fdo, irp);
break;
case IRP_MN_REMOVE_DEVICE:
status = PnpRemoveDeviceHandler(fdo, irp);
break;
...
default:
PnpDefaultHandler(fdo, irp);
};
return status;
}
![Page 60: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/60.jpg)
6060
DispatchPower例程
NTSTATUS DispatchPower (IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
PWDM_DEVICE_EXTENSION dx =
(PWDM_DEVICE_EXTENSION)fdo->DeviceExtension;
PoStartNextPowerIrp( Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver( dx->NextDevice, Irp);
}
![Page 61: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/61.jpg)
6161
DispatchWmi例程
驱动程序对 WMI的支持主要是基于对主代码为IRP_MJ_SYSTEM_CONTROL的 IRP的支持。为了能接收到这种IRP,必须先注册这种需求:– IoWMIRegistrationControl(fdo, WMI_ACTION_REGISTER);
调用 IoWMIRegistrationControl函数的恰当位置是在AddDevice例程中,注册完成后,一旦系统认为可以安全地向驱动程序发送系统控制 IRP时,它就向驱动程序发出一个IRP_MJ_SYSTEM_CONTROL请求,以获得设备的详细寄存信息
对于 WDM驱动程序而言,系统控制 IRP的分发例程DispatchWmi是必须提供的,一般的做法是委托 WMILIB来处理系统控制 IRP, WMILIB实际上是一个内核模式 DLL,它导出的服务可以被其他驱动程序调用
![Page 62: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/62.jpg)
6262
其他可选的例程
Windows应用程序与设备驱动程序打交道主要是通过CreateFile、 ReadFile、 WriteFile 和DeviceIoControl等 Win32 API来进行的,这些 API对应着驱动程序的一些分发例程
![Page 63: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/63.jpg)
6363
DispatchWrite例程NTSTATUS DispatchWrite( IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
PWDM_DEVICE_EXTENSION dx =
(PWDM_DEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION pIrpStack =
IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG BytesTxd = 0;
ULONG WriteLen = pIrpStack->Parameters.Write.Length;
if( WriteLen>SHARED_MEMORY_SIZE)
status = STATUS_INVALID_PARAMETER;
else if( WriteLen>0)
{
RtlMoveMemory( SharedMemory,
Irp->AssociatedIrp.SystemBuffer, WriteLen);
BytesTxd = WriteLen;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = BytesTxd;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
![Page 64: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/64.jpg)
6464
WDM驱动程序编程实例
驱动程序中除了 DriverEntry例程必须以 DriverEntry命名以外,其他例程都可以使用程序员自定义的名字,并且都要由 DriverEntry例程向系统注册
![Page 65: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/65.jpg)
6565
开发 WDM驱动程序的一般方法
对照相关设备的资料仔细分析驱动程序应实现哪些功能 根据 WDM设备驱动程序的组成,采用渐进的方法对驱动程序进行模块化设计
![Page 66: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/66.jpg)
6666
开发 WDM驱动程序的一般方法
一个 WDM设备驱动程序通常完成以下工作:– 初始化– 创建、删除设备– 即插即用处理– 访问硬件– 处理电源管理– 使用 WMI
– 处理 Win32I/O及控制请求 将这些功能划分为不同模块
![Page 67: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/67.jpg)
设备驱动程序的创建与调试过程
观察与体验观察与体验
![Page 68: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/68.jpg)
6868
构造 WDM驱动程序开发环境
1 )安装 Microsoft Visual Studio .NET
2 )安装 Microsoft Windows DDK
3 )安装 Debugging Tools for Windows
![Page 69: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/69.jpg)
6969
构造 WDM驱动程序开发环境
安装成功 Visual Studio .NET后,运行界面如下图所示
![Page 70: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/70.jpg)
7070
构造 WDM驱动程序开发环境
安装成功 Windows DDK后,菜单栏如下图所示
![Page 71: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/71.jpg)
7171
构造 WDM驱动程序开发环境
安装成功 Debugging Tools后,菜单栏如下图所示
![Page 72: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/72.jpg)
7272
编辑、编译和链接
1 )编写驱动程序源文件,包括:– WdmDriver.h
– guid.h
– init.cpp
– Pnp.cpp
– Wmi.cpp
– Dispatch.cpp
– Wdm.mof
![Page 73: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/73.jpg)
7373
编辑、编译和链接
2 )编译链接驱动程序,生成驱动程序可执行文件 成功编译一个驱动程序需要在要被编译的源文件目录下面提
供三个文本文件(三个文件都没有扩展名):– MAKEFILE
– SOURCES
– DIRS
驱动程序生成工具 BUILD从这三个文件读取输入,并且创建BUILD.LOG、 BUILD.ERR等文件作为输出,如果一切正常,执行 BUILD的最后结果是创建驱动程序的可执行版本,其文件类型是 .SYS
![Page 74: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/74.jpg)
7474
编辑、编译和链接
2 )编译链接驱动程序,生成驱动程序可执行文件 驱动程序的编译 单击开始所有程序 Development Kits Windows DDK Build Enviroments Win XP Checked Build Enviroment,将出现一个控制台窗口
使用 cd命令进入待编译驱动程序所在的目录,键入 build命令即可编译
运行 build命令只编译需要重新编译的文件 , 而 build -c 命令则强迫编译器重新编译所有的文件
![Page 75: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/75.jpg)
7575
编辑、编译和链接
![Page 76: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/76.jpg)
7676
安装驱动程序
设备驱动程序的自动安装由一个以 inf为扩展名的文本文件控制。正确的保存在 Windows 系统上的一个 inf文件,允许自动安装驱动程序文件,或者在对话框支持下安装驱动程序文件
![Page 77: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/77.jpg)
7777
安装驱动程序
驱动程序的安装过程: 首先进入控制面板,选择“添加新硬件”, “下一步”后系
统会扫描硬件,选择“是,硬件已经连接好”,然后在对话框的底部选择“添加新的硬件设备”,接着选择“安装我手动从列表选择的硬件”,确定后再选“从磁盘安装”,“浏览”找到 WdmDriver.inf文件所在的文件夹,单击“确定”。从接下来的对话框中指定 WdmDriver.sys所在的位置,系统将把驱动程序 WdmDriver.sys复制到 Windows系统的 system32\drivers文件夹中
![Page 78: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/78.jpg)
7878
安装驱动程序
安装之后, WdmDriver应该出现在设备管理器的“其它设备”类别中,选中该设备,单击“属性”,可以查看驱动程序的信息 :
![Page 79: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/79.jpg)
7979
驱动程序测试
测试程序 TestWdm.cpp执行以下操作:– 打开 wdmdriver设备– 读存储在共享内存缓冲区中的第一个 DWORD。– 把 0xabcdef01写到缓冲区– 从缓冲区中读取 4 个字节– 往缓冲区写 5 个字节,因为设置的缓冲区大小只有 4 个字节,
所以会失败,并报错– 关闭设备
![Page 80: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/80.jpg)
8080
驱动程序测试
如果驱动程序工作正常,屏幕显示为:
![Page 81: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/81.jpg)
8181
驱动程序测试
如果驱动程序工作不正常,则需要进行调试 支持驱动程序调试的工具为 Microsoft的 Debugging Tools for Windows
WinDbg 是一个功能齐全的调试器,支持 C 语言源代码级调试,可以使用驱动程序的源代码设置各种断点
WinDbg的使用需要双机环境,目标机运行驱动程序和测试应用程序,宿主机运行调试器,使用起来不是特别方便
![Page 82: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/82.jpg)
8282
驱动程序测试
WinDbg
主机和目标计算机通过无 Modem串行电缆通过串行口通讯
![Page 83: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/83.jpg)
8383
驱动程序调试
WinDbg目标机配置: 目标机器的 boot.ini增加一行启动选项: /debug /debugport=com1 /baudrate=115200
![Page 84: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/84.jpg)
8484
驱动程序调试
WinDbg宿主机配置: 启动 WinDBD
在 File菜单中选择 Symbol File Path设置符号文件搜索路径
在 File菜单中选择 Source File Path设置源文件搜索路径
在 File菜单中选择 Image File Path设置可执行文件搜索路径
![Page 85: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/85.jpg)
8585
驱动程序调试
WinDbg宿主机配置: 启动 WinDBD,在 File菜单中选择 Kernel Debug,在出
现的对话框中设置串行端口和波特率
![Page 86: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/86.jpg)
8686
驱动程序调试
设置好串行端口和波特率后单击确定,出现如下画面,宿主机等待与目标机的连接:
![Page 87: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/87.jpg)
8787
驱动程序调试
在目标机中选择“启用调试程序”选项引导机器,则在宿主机上显示与目标机的连接信息:
![Page 88: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/88.jpg)
8888
驱动程序调试
如果目标机器正在运行,在 WinDbg命令窗口输入 Ctrl+Breakc,则暂停目标机器的运行
从 File菜单选择 open source file打开驱动程序源文件 把光标移到有分号的源代码行上 单击断点按钮,可以在驱动程序源文件中设置断点,设置断点源代码变
为红色 单击 F5键,可恢复目标机器运行 :
![Page 89: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/89.jpg)
8989
驱动程序调试
![Page 90: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/90.jpg)
9090
驱动程序调试
在目标机上运行测试程序,则系统将在驱动程序的断点处中断
![Page 91: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/91.jpg)
9191
驱动程序调试
断点
![Page 92: Windows 环境下的程序设计](https://reader033.vdocuments.site/reader033/viewer/2022061520/56814207550346895daded0e/html5/thumbnails/92.jpg)
Thoughts Change Life意念改变生活