陆陆续续做过一些驱动的开发,但是一直以来都没有系统的学习过。这次重新阅读《windows驱动开发技术详解》(张帆,史彩成等编著),写博客记录一下,用以加深自己对驱动的理解。
驱动对象(DRIVER_OBJECT)
每个驱动程序会有唯一的驱动对象与之对应,并且这个驱动对象是在驱动加载的时候,被内核中的对象管理程序所创建的。
驱动对象用DRIVER_OBJECT来表示,内核对一个驱动只加载一个实例。对于DRIVER_OBJECT的说明,详见:http://msdn.microsoft.com/en-us/library/windows/hardware/ff544174(v=vs.85).aspx
说明一下其中的一个成员:DeviceObject。
MSDN上面是这么定义:
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 of DEVICE_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指定。
参考:http://msdn.microsoft.com/en-us/library/windows/hardware/ff543147(v=vs.85).aspx
需要说明的是:
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也处于同一个水平层次。
简单回顾了一下驱动的一些基本概念,其实这些资料基本来自于《windows驱动开发技术详解》这本书。都是一些比较抽象的概念,至于具体应用,待续...