没事写点基础的东西,有写的不当的地方,希望能指出。
写过驱动或者正在学习驱动编程的人可能都碰到了驱动对象和设备对象。DriverObject和DeviceObject的关系。这里就做个说明吧。
首先来看看这两个结构体定义,从中我们可以发现一些有意思的东西。
<textarea cols="86" rows="15" name="code" class="cpp">typedef struct _DRIVER_OBJECT { CSHORT Type; CSHORT Size; // // The following links all of the devices created by a single driver // together on a list, and the Flags word provides an extensible flag // location for driver objects. // PDEVICE_OBJECT DeviceObject; ULONG Flags; // // The following section describes where the driver is loaded. The count // field is used to count the number of times the driver has had its // registered reinitialization routine invoked. // PVOID DriverStart; ULONG DriverSize; PVOID DriverSection; PDRIVER_EXTENSION DriverExtension; // // The driver name field is used by the error log thread // determine the name of the driver that an I/O request is/was bound. // UNICODE_STRING DriverName; // // The following section is for registry support. Thise is a pointer // to the path to the hardware information in the registry // PUNICODE_STRING HardwareDatabase; // // The following section contains the optional pointer to an array of // alternate entry points to a driver for "fast I/O" support. Fast I/O // is performed by invoking the driver routine directly with separate // parameters, rather than using the standard IRP call mechanism. Note // that these functions may only be used for synchronous I/O, and when // the file is cached. // PFAST_IO_DISPATCH FastIoDispatch; // // The following section describes the entry points to this particular // driver. Note that the major function dispatch table must be the last // field in the object so that it remains extensible. // PDRIVER_INITIALIZE DriverInit; PDRIVER_STARTIO DriverStartIo; PDRIVER_UNLOAD DriverUnload; PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; } DRIVER_OBJECT; typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; // ntndis</textarea>
<textarea cols="86" rows="15" name="code" class="cpp">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; struct _IRP *CurrentIrp; PIO_TIMER Timer; ULONG Flags; // See above: DO_... ULONG Characteristics; // See ntioapi: FILE_... 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; // // The following field is for exclusive use by the filesystem to keep // track of the number of Fsp threads currently using the device // 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; </textarea>
我们发现在DRIVER_OBJECT中有一个指向DEVICE_OBJECT的指针,这个指针是什么时候进行赋值的呢。一会说。再看看DEVICE_OBJECT这个结构,我们发现其中有一个回指向DRIVER_OBJECT的指针,还有一个 NextDevice,这也是一个DEVICE_OBJECT,这又是什么意思呢。
现在我们来一点点的解答。要对这些做一个解答,那么就必须说说IoCreateDevice这个函数。这个函数时用来干什么的。大家都只要是用来生产设备对象的。这个函数机会在内核驱动都有时有见到的。这个函数到底做了什么呢。在这个函数中简单的说就是生成后一个DeviceObject,并进行必要的初始化操作。然后将DeviceObject中的DriverObject进行填充为当前的DriverObject。并将这个设备对象插入到这个驱动的设备列表中。就是这一个函数完成了,之前提到的赋值问题。
这样DriverObject就和DeviceObject关联起来了。那为什么需要关联起来呢。有一个值得注意的就是,系统的请求是发给设备对象的而不是驱动对象的。可是我们根本就没有位设备对象编写处理请求的处理函数。有人会说,在DeiverEntry中初始化的那些不就是吗。其实这些初始化的MajorFunction我们看到都是在DriverObject中保存着。当有请求过来时,设备对象可以根据相对应的Driverobject找到MajorFunction表,然后再IRP的IO stack loction中可以定位现在应该调用哪个函数进行处理。这样就不难说明为什么要在devicobject中有一个回指的缘故的。
而在驱动卸载的时候,我们需要将设备对象删除掉。如果一个驱动,生成了很多对象,那么我们怎么一个个删除了。除了使用很多全局变量来存储每个生成的设备对象,明显是不可取的。我们可以将驱动对象保存下来,这样,在需要删除所有的设备对象时,就可以通过DriverObject中的DeviceObject,以及DEVICE_OBJECT中的NextDevice来得到所以得设备对象了。在xp之上,我们不需要手动去得到,可以直接调用IoEnumerateDeviceObjectList得到。
今天就说到这里了。