15、Windows驱动开发技术详解笔记(11) 基本概念
时间:2010-10-23 来源:edwardlewiswe
驱动程序中,不能使用编译器运行时函数,甚至C语言中的malloc,C++的new函数都不能用,因为他们在VC中的实现都是调用了Win32 API了。要用的话,必须自己重载new等运算符。大部分运行时函数是通过Win32 API实现的。在内核模式下无法调用用户模式的程序,而用户模式下通过参数审核可以调用内核态程序。
内核态的运行时函数来替换用户态的运行时函数,一般形如RtlXXXX。
设备名称用UNICODE字符串指定,且必须是“\Device\[设备名]”形式。用户模式下,通过两种方法找到设备:
法1:符号连接
法2:通过设备接口。
一般虚拟设备用FILE_DEVICE_UNKNOWN类型。
******************
"采用C++编程,所以需要用extern "C",因为我们导入的是C的函数的符号表",系统内核是有C语言编写的,连接时要调用相应的函数,所以应当把驱动头文件编译成C语言形式。
10、用build编译
Build首先设置环境变量,然后调用nmake。nmake解析makefile,调用cl,link来编译程序。
Makefile中依赖关系如下声明:
A:B,C
Action
说明:A依赖于B和C。如果A的最后修改时间早于B和C任一个文件的最后修改时间,则执行action。Action前面是tab。
用VC编译,我们在另一篇中论述。
11、查看调试信息
法一:打印信息
尽量用KdPrint,在free版本中不显示。同prrinf使用,双括号,宽字符用%ws或%S。
法二:用DriverStudio中的DriverMonitor。不过可以用免费的DbgView,下载地址是:
http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx
12、加载驱动
NT式驱动程序的加载,是基本服务的方式加载的。设备驱动程序的动态加载主要由服务控制管理程序(SCM)系统组件完成的。Windows服务应用程序遵循控制管理器。Driver Service是Windows服务的一个特例,它遵守Windows服务的协议。
图 加载 P72
图 卸载驱动流程 P72
代码 加载和卸载驱动代码
关于WDM驱动的手工加载,见[1]。
13、NT驱动程序的基本结构
1)数据结构
DEVICE_OBJECT
The DEVICE_OBJECT structure is used by the operating system to represent a device object. A device object represents a logical, virtual, or physical device for which a driver handles I/O requests.
http://msdn.microsoft.com/en-us/library/ff543147%28VS.85%29.aspx
每个设备对象指针指向向一个设备对象,最后一个设备对象指向空。
图 设备对象布局图 P92
设备扩展对象定义自己定义的结构体,驱动程序中尽是避免使用全局变量,因为会影响同步,而把全局变量存在设备扩展里。
driver object
Each driver object represents the image of a loaded kernel-mode driver. A pointer to the driver object is an input parameter to a driver's DriverEntry, AddDevice, and optional Reinitialize routines and to its Unload routine, if any.
每个驱动程序与唯一的驱动对象相对应,这个驱动对象是在驱动加载时候,被内核中的对象管理器创建。驱动对象为驱动和个实例被内核加载,并且一个驱动只能加载一个实例。
图 驱动对象布局图 P88
其它参见:
http://www.cnblogs.com/mydomain/archive/2010/10/16/1853235.html
14、DriverEntry主要是对系统进程创建的驱动对象进行初始化。
15、WDM程序的基本结构
一般都是基于分层的,完成一个设备的操作,至少要由两个驱动设备共同完成。一个是PDO(物理设备对象),一个是FDO(功能设备对象),其关系是附加与被附加关系。当PC中插入某个设备时,总线驱动自动创建PDO,由PDO引出FDO。
图 FDO与PDO P103
过滤驱动不是必须的。
与NT的不同:
· 增加了对AddDevice函数的设备。操作系统加载PDO后,调用驱动的AddDevice例程,AddDevice例程负责创建FDO,并且附加到PDO之上。
·设备对象在AddDevice例程中创建。
·必须加入IRP_MJ_PNP的派遣回调函数。
PDO会通过AttachedDevice子域知道它上面的设备是FDO或过滤驱动,但是不知道下面的,可以通过定制自己的设备扩展来记录地址。
16、设备的层次结构
图 设备对象堆栈 P104
图 垂直结构 P111,P113
参考
【1】Windows 驱动开发技术详解
【2】http://msdn.microsoft.com/en-us/library/ff565757%28VS.85%29.aspx
【3】Windows驱动学习笔记,灰狐