Windows驱动开发基础(五)驱动程序的数据结构

Windows驱动开发基础:驱动程序的数据结构。转载请标明出处:http://blog.csdn.net/ikerpeng/article/details/38794405


I/O管理器定义了一些数据结构,这些很重要。


1. 驱动对象(DRIVER_OBJECT)


通过一个typedef 定义的以一个struct:

<span style="font-family:Microsoft YaHei;">typedef struct
{
PDEVICE_OBJECT DeviceObject; //指向驱动程序创建的设备对象</span>
<span style="font-family:Microsoft YaHei;">UNICODE_STRING  Drivername // 驱动名称
PUNICODE_STRING HardwareDatabase; //记录的是设备的硬件数据库名,这里同样用Unicode字符串记录
PFAST_IO_DISPATCH FastIoDispatch;//文件驱动中用到的派遣函数
PDRIVER_INITIALIZE DriverInit;//指向DriverEntry函数的,这是通过IO管理器来建立的。
PDRIVER_STARTIO DriverStartIo;//记录StartIO例程的函数地址,用于串行化操作
PDRIVER_UNLOAD DriverUnload;//指定驱动卸载时所用的回调函数地址
PDRIVER_DISPATCH MajorFunction[IRP_MJ_NUM+1];//指向驱动程序的DispatchXXX函数指针的数组
}DRIVER_OBJECT,*PDRIVER_OBJECT;指向驱动程序的DispatchXXX函数指针的数组</span>

 里面有一些重要的数据结构:


DeviceObject: 设备对象,可能是一个或多个。由程序猿自己创建,驱动程序被卸载的时候,遍历每一个DriverObject并删除;

 

DeviceName:设备名称,保存在Unicode字符串里面  

HardwareDatabase:


HardwareDatabase记录的是设备的硬件数据库名,这里同样用Unicode字符串记录。该字符串一般为HKEY_LOCAL_MACHINE\Hardware\DESCRIPTION\System,是一个注册表路径。
FastIoDispatch:


文件驱动中用到的派遣函数。指向这个驱动程序的FastIO入口点定义的一个结构。这个成员只能通过FSDs和网络传输驱动来使用。
DriverInit:


指向DriverEntry函数的,这是通过IO管理器来建立的。
DriverStartIo:


记录StartIO例程的函数地址,用于串行化操作,如果一个驱动程序没有StartIo函数,这个成员将是NULL。
DriverUnload:


指定驱动卸载时所用的回调函数地址,如果驱动程序没有卸载函数,这个成员将是NULL。
MajorFunction[IRP_MJ_NUM+1]:


指向驱动程序的DispatchXXX函数指针的数组。每个驱动程序至少要设置一个DispatchXXX函数指针在这个数组里来处理这个驱动程序IRP请求包。任何一个驱动程序可以设置和IRP_MJ_XXX代码一样多的DispatchXXX来处理IRP请求包.每个DispatchXXX结构如下:
NTSTATUS DispatchXXX(IN PDEVICE_OBJECT DeviceObjec, IN PIRP Irp);


2. 设备对象(DeviceObject):


一张图理一下里面的成员的关系:

                                          

每个驱动都会有设备对象,每一个设备对象都有一个指针指向下一个设备对象(最后一个为空)。结构体定义如下:

<span style="font-family:Microsoft YaHei;">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;
    /*当前IRP结构*/
    struct _IRP *CurrentIrp;
    PIO_TIMER Timer;
    /*设备对象的特性标志*/
    ULONG Flags;
    ULONG Characteristics;
    _volatile 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;
    /*
    *下列成员用于支持文件系统的互斥操作
    *以便对文件系统处理线程使用设备的计数保持跟踪
    */
    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;</span>

下面分别描述设备对象中驱动程序可访问成员的具体含义:


PDRIVER_OBJECT DriverObject:指向驱动程序中的驱动对象。同属一个驱动程序的驱动对象指针都指向同一个驱动对象。

PDEVICE_OBJECT NextDevice:指向下一个设备对象。这里的下一个设备对象是同一个驱动程序创建的若干设备对象中的一个。每个设备对象会根据

NextDevice成员形成链表,从而遍历每个设备对象。在每次成功调用IoCreateDevice 后,I/O管理器就会更新该链表。当驱动被卸载时,需要遍历该链表,删除每个设备对象。


PIRP CurrentIrp:如果驱动使用StartIO例程,此成员将指向当前的IRP结构,否则为NULL。


ULONG Flags:此成员是一个32位的无符号整型变量,每个位有不同的含义。可通过按位取“或”操作为新创建的设备对象设置不同的特性。


ULONG Characteristics:此成员说明设备对象的特性,当驱动程序调用IoCreate-Device时,可设置FILE_REMOVABLE_MEDIA(表示存储设备支持可移动介质)、FILE_READ_ONLY_DEVICE(表示设备不能写)、FILE_FLOPPY_DISKETTE(表示设备是软盘设备)等值。


PVOID DeviceExtension:指向设备扩展对象。


DEVICE_TYPE DeviceType:指明设备的类型,由IoCreateDevice设置,根据设备的需要填写相应的设备类型。


CCHAR StackSize:在多层驱动的情况下,驱动与驱动之间形成类似堆栈的结构。IRP会依次从最高层传递到最底层。StackSize就是用于指定发送到该驱动的IRP在堆栈位置的最小层数的。IoCreateDevice在一个新创建的设备对象中设置该成员。


ULONG AlignmentRequirement:进行数据传输的时候,规范设备的地址对齐


其中的DeviceType:指明设备的类型,当作为一个虚拟的设备的时候选择:FILE_DEVICE_UNKNOWN.



3. 设备扩展:


设备对象记录的是通用的信息,而一些特殊的信息则要记录于设备扩展里面了。

在驱动程序里面最好不要使用全局变量,这往往导致函数的不可重入性。将全局变量以设备扩展的形式存储,并加以保护措施,这样可以解决这个问题。


参考文献:


《Windows驱动开发技术详解》

http://www.cnblogs.com/qintangtao/archive/2013/04/09/3009790.html

 

你可能感兴趣的:(windows,7)