Window XP驱动开发(十) 驱动程序的基本结构
来源:互联网 发布:潍坊行知学校在哪个区 编辑:程序博客网 时间:2024/04/29 03:08
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家提出意见,一起讨论!
参考书籍<<Windows驱动开发技术详解>>
一、数据结构
1、驱动对象(DRIVER_OBJECT)
每个驱动程序会有唯一的驱动对象与之对应,且这个驱动对象是在驱动加载时,
被内核中的对象管理程序所创建的。
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; // 每个驱动程序会有一个或多个设备对象。其中每个 // 设备对象都有一个指向下一个驱动对象,最后一个设备对象指向空。 // 此处的DeviceObject指赂驱动对象的第一个设备对象。 // 通过DeviceObject就可以遍历驱动对象里的所有设备对象。 // 设备对象是由程序员自己创建的,而而OS完成。 // 在驱动卸载时,遍历每个设备对象,并将其删除。 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; // 驱动程序的名字,该串一般为\Driver\[驱动程序名称 ] // // The following section is for registry support. Thise is a pointer // to the path to the hardware information in the registry // PUNICODE_STRING HardwareDatabase; // 记录的是设备的硬件数据库键名。 // 这里同样用UNICODE字符串记录。 // 一般为\REGISTRY\MACHINE\HARDWAR\DESCRIPTORION\SYSTEM // // 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; // 记录StartIO例程的函数地址 PDRIVER_UNLOAD DriverUnload; // 指向驱动卸载时所用的回调函数地址 PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; } DRIVER_OBJECT;typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
2、 设备对象(DEVICE_OBJECT)
每个驱动程序会创建一个或多个设备对象,用DEVICE_OBJECT数据结构表示,每个设备对象都会有一个指针指向下一个设备对象,因此形成一个设备链。
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; // 指向下一个设备对象。这里指出的是,如果有更高一层的驱动附加 // 到这个驱动时,AttachedDevice指向的就是那个更高一层的驱动 struct _IRP *CurrentIrp; // 在使用StartIO例程时,此域指向的是当前IRP结构。 PIO_TIMER Timer; ULONG Flags; // 是一个32位的无符号整型。 ULONG Characteristics; // See ntioapi: FILE_... __volatile PVPB Vpb; PVOID DeviceExtension; DEVICE_TYPE DeviceType; // 设备的类型。 CCHAR StackSize; // 在多层驱动情况下,驱动与驱动之间会形成类似堆栈的结构, // IRP会依次从最高层传递到最低层。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; //// The following structure is pointed to by the SectionObject pointer field// of a file object, and is allocated by the various NT file systems.//typedef struct _SECTION_OBJECT_POINTERS { PVOID DataSectionObject; PVOID SharedCacheMap; PVOID ImageSectionObject;} SECTION_OBJECT_POINTERS;
===========================================================================================================
设备对象的结构如下图:
3、设备扩展
设备对象记录“通用”设备的信息,而另外一些“特殊”信息记录在设备扩展中。各个设备扩展由程序员定义,每个设备的设备扩展也不尽相同。
设备扩展由I/O管理器创建的。并保存在非分页的内存中。
在设备扩展中会记录下列内容:
(1)设备对象的反向指针
(2)设备状态或驱动环境信息
(3)中断对象指针
(4)控制器对象指针
二、驱动的基本结构
1、NT式驱动的基本结构
1、1 驱动加载过程与驱动入口函数(DriverEntry)
参考我的另一篇博客: http://blog.csdn.net/chenyujing1234/article/details/7565364
1、2 创建设备对象
会调用IoCreateDevice函数
IoCreateDevice( __in PDRIVER_OBJECT DriverObject, // 驱动对象的指针。 __in ULONG DeviceExtensionSize, // 指定设备扩展的大小,I/O管理器会根据这个大小// 在内存中创建设备扩展,并与驱动对象关联。 __in_opt PUNICODE_STRING DeviceName,// 设置设备对象的名字。 __in DEVICE_TYPE DeviceType, __in ULONG DeviceCharacteristics,// 设备设备对象的特征 __in BOOLEAN Exclusive, // 设置设备对象是否为内核算模式下使用 __out __drv_out_deref( __drv_allocatesMem(Mem) __drv_when((((inFunctionClass$("DRIVER_INITIALIZE")) ||(inFunctionClass$("DRIVER_DISPATCH")))), __drv_aliasesMem) __on_failure(__null)) PDEVICE_OBJECT *DeviceObject // I/O管理器负责创建这个设备对象,并返回对象的地址。 );
设备名称用UNICODE字符串指定,且字符串必须是"\Device\[设备名]"的形式。
在Windows下的所有设备都是以类似的名字命令的。
当然也可以不指定设备名字。如果在IoCreateDevice没指定设备名字,I/O管理器会自动分配一个数字作为设备的设备名。
eg: \Device\00000001
如果指定了设备名,只能被内核模式下的其他驱动所识别。但在用户模式下的应用程序无法识别这个设备。
让应用程序能识别设备有两种方法:
(1)通过符号链接找到设备。(常用)
(2)通过设备接口找到设备。
符号链接可以理解为设备对象起了一个“别名”。设备对象的名称只能被内核模式的驱动识别,
而别名也可以被用户模式下的APP识别.
eg: 常说的C盘,指向的“C:”的符号链接,其真实对象是“\Device\HarddiskVolume1“
创建符号链接的函数是
NTSTATUS
IoCreateSymbolicLink(
__in PUNICODE_STRING SymbolicLinkName,
__in PUNICODE_STRING DeviceName
);
2、WDM式驱动的基本结构
WDM驱动结构请参考我的另一篇文章
http://blog.csdn.net/chenyujing1234/article/details/7568029
WDM驱动的DriverEntry与NT式驱动的DriverEntry有以下几个不同:
(1)增加了对AddDevice函数的设置。
因为NT驱动是主动加载设备的,也就是一旦加载驱动就创建设备。
而WDM驱动是被动加载设备的。OS必须加载PDO后,调用驱动的AddDevice例程,
AddDevice负责创建FDO,并附加到PDO上。
(2)必须加入IRP_MJ_PNP的派遣回调函数。
它主要负责计算机中即插即用的处理。
具体的回调函数可以参照我的文章
http://blog.csdn.net/chenyujing1234/article/details/7580315
- Window XP驱动开发(十) 驱动程序的基本结构
- Window XP驱动开发(二十二) 驱动程序的同步处理
- Window XP驱动开发(二十二) 驱动程序的同步处理
- Window XP驱动开发(十六) XP下新建驱动程序工程并编译的第二种方法
- Window XP驱动开发(二十)Window驱动的内存管理
- Window XP驱动开发(二十)Window驱动的内存管理
- Window XP驱动开发(二十一) 过滤驱动程序
- Window XP驱动开发(十五) 驱动程序调用驱动程序(以文件句柄形式)
- Window XP驱动开发(十六) 驱动程序调用驱动程序(通过设备指针)
- Window XP驱动开发(二十四) 驱动程序工程用 DDK命令行编译
- 驱动程序的基本结构
- 驱动程序的基本结构
- 驱动程序的基本结构
- Window XP驱动开发(十七) CY7C68013A GPIF的配置
- Window XP驱动开发(二十三)Window驱动的派遣函数
- linux驱动由浅入深系列:驱动程序的基本结构概览之一(第一个驱动程序)
- linux驱动由浅入深系列:驱动程序的基本结构概览之二(详解驱动注册过程)
- Windows驱动程序的基本结构
- 在Magento1.4.2中创建关联产品后不显示的问题
- QTP描述性编程
- 无法启动OracleOraDB10g_home1TSNListener服务
- Form个性化--调用Procedure .
- hadoop安装配置
- Window XP驱动开发(十) 驱动程序的基本结构
- 开始使用C++11的9个理由
- EXT获得combobox文本值
- Java已死?九百万程序员说不
- synchronized
- Android应用进入爆发期 手机游戏仍是市场重心
- Observer模式
- 11级_Java_曹建波5.21 数据库的基本概念
- Oracle 释放过度使用的Undo表空间