WDM驱动程序的框架

上传人:cn****1 文档编号:498039477 上传时间:2023-03-03 格式:DOCX 页数:12 大小:23.18KB
返回 下载 相关 举报
WDM驱动程序的框架_第1页
第1页 / 共12页
WDM驱动程序的框架_第2页
第2页 / 共12页
WDM驱动程序的框架_第3页
第3页 / 共12页
WDM驱动程序的框架_第4页
第4页 / 共12页
WDM驱动程序的框架_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《WDM驱动程序的框架》由会员分享,可在线阅读,更多相关《WDM驱动程序的框架(12页珍藏版)》请在金锄头文库上搜索。

1、WDM 驱动程序的框架1. DriverEntry ()DDK中定义的函数原型如下:NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath);DriverEntry 的第一个参数是一个指针,指向一个刚被初始化的驱动程序对象,该对象就代表你的驱动程序。DriverEntry的第二个参数是设备服务键的键名。如果该例程执行成功,则返回STATUS_SUCCESS,如果 失败,则依据失败状态返回定义在ntstatus.h中的错误值。这是驱动程序的入口函数,相当于用户态程序的main()函数

2、,它在驱动程序被加载进内存的时候调用。主 要工作是把各种函数指针填入驱动程序对象。这些指 针为操作系统指明了驱动程序容器中各种子例程的位 置,这样,该驱动程序对象关联的设备对象在接收到上层的 IRP 的时候,就会通过驱动程序对象中设置的 函数 指针,找到相应的派遣函数来做处理。Eg.一个简单的DriverEntry ()代码片断:DriverObject-DriverUnload =DriverUnload;DriverExtension-AddDevice = AddDevice;DriverObject-DriverStartIo = StartIo;DriverObject-MajorF

3、unction IRP_MJ_CREATE =DriverDispatchCreate;DriverObject-MajorFunction IRP_MJ_CLOSE = DriverDispatchClose;DriverUnload指向驱动程序的清除例程。I/O管理器会在卸载驱动程序前调用该例程。通常,WDM驱动 程序的DriverEntry例程一般不分配任何资源,所以DriverUnload例程也没有什么清除工作要做。DriverDispatchxxx驱动程序可能仅需要处理几种类型的IRP,所以至少应该设置与那几种IRP类型相 对应的指针元素,使它们指向相应的派遣函数。AddDevice

4、 指向驱动程序的 AddDevice 函数,在该函数中主要创建一个设备对象并把它连接到以 pdo 为底的设备堆栈中。2. AddDevice()DDK中定义的函数原型如下:NTSTATUSXxxAddDevice (IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PhysicalDeviceObject);AddDevice 函数的第一个参数是指向该驱动的驱动对象的指针,第二个参数代表由底层驱动创建的物理设 备对象。对于功能驱动程序,其AddDevice函数的基本职责是创建一个设备对象并把它连接到以pdo为底的设备堆 栈中。相关步骤如下:tru

5、e2. 寄存一个或多个设备接口,以便应用程序能知道设备的存在。另外,还可以给出设备名并创建符 号连接。 true3. 初始化设备扩展和设备对象的 Flag 成员。 true4. 调用 IoAttachDeviceToDeviceStack() 函数把新设备对象放到堆栈上。关于AddDevice ()函数:在规范的WDM程序中,创建设备对象的任务本来该由AddDevice函数来做, 而这个函数也是通过驱动程序对象的一个函数指针来定位的。在这种规范的WDM程序中,一旦有新硬件 加入,系统就会自动通过驱动程序对象的函数指针找到AddDevice函数,并调用它来创建设备对象。但是 在这里,并不是在为实

6、际存在的硬件写驱动,而只是写一个内核模式下的程序,因此就只需要在 DriverEntry 函数中创建一个设备对象, 然后创建设备链接(可选)就可以了。(以上为网上摘录)3. DriverDispatchXXX一般派遣函数有两个参数:一个指向DEVICE_OBJECT结构的指针,指向由驱动在AddDevice(或DriverEntry) 中创建的设备对象。第二个参数是指向一个 IRP 结构的指针。派遣函数DriverDispatchXXX主要负责处理上层的IRP。这里先要提一下,每个IRP都与两个数据结构相关 联,就是IRP本身和IRP StackIO_STACK_LOCATION结构。在这两个

7、结构里面,包含了所有上层传递 给本层设备对象的信息。最重要的一个信息就是:在IO_STACK_LOCATION结构中,包含了 IRP的功能码 MajorFunction和MinorFunction(IRP的功能码标识了该IRP具体是什么请求,比如读请求的MajorFunction值为 IRP_MJ_READ)。DriverDispatch 函数的处理流程一般是这样的:首先通过 IRP 获得 IPR Stac(k IoGetCurrentIrpStackLocation(irp);然后从 IRP Stack 中得到该 IRP 的主功能码 MajorFunction (IRPStack-Major

8、Function),判 断主功能码并做相应处理;处理完该请求后,根据具体情况选择完成该请求或者向下一层设备对象传递该 IRP。探如果获得的主功能码为:IRP_MJ_DEVICE_CONTROL,则还需要通过IRPStack-Parameters.DeviceIoControl.IoControlCode 获得具体的 IOCTL 的控制代码。最后一步,如果需要完成该请求,那么应该先设置IRP结构中的IoStatus域,然后调用函数IoCompleteRequest () :pIrp-IoStatus.Status = STATUS_SUCCESS;pIrp-IoStatus.Informatio

9、n = information;IoCompleteRequest(pIrp, IO_NO_INCREMENT);如果需要向下一层设备对象传递该IRP,则要先初始化往下传递的IRP对应IRP Stack(可以直接将当前的IRP Stack复制给下层IRP Stack),然后调用IoCallDriver函数往下层传递该IRP:IoCopyCurrentIrpStackLocationToNext(pIrp);status = IoCallDriver(pLowerDeviceObj, pIrp);4. DriverUnload函数原型:VOID DriverUnload (PDRIVER_OBJ

10、ECT DriverObject)DriverUnload函数的主要任务是将创建的设备对象和符号连接删除掉,当然如果在程序中还分配了其他内 存需要释放,也是在这里完成。IoDeleteSymbolicLink ();IoDeleteDevice ( );注意这两个函数的调用顺序,要先删除符号链接再删除设备对象。如果DriverEntry例程返回一个失败状态代码,系统将不再调用DriverUnload例程。所以,不能让DriverEntry 例程出错后产生任何副作用,必须在它返回错误代码前消除副作用。 关于 IRPIRP是I/O request packet的缩写,即I/O请求包。驱动与驱动之间

11、通过IRP进行通信。而使用驱动的 应用层调用的 CreatFile,ReadFile,WriteFile,DeviceIoControl 等函数,说到底也是使用 IRP 和驱动进行通 信。IRP分为两个部分:首部和IRP堆栈,下面列出了常用的一些域:IRP 首部:IO_STATUS_BLOCK IoStatus 包含 I/O 请求的状态PVOID Associatedlrp.SystemBuffer如果执行缓冲区I/O,这个指针指向系统缓冲区PMDL MdlAddress如果直接I/O,这个指针指向用户缓冲区的存储器描述符表PVOID UserBufferI/O缓冲区的用户空间地址IRP 堆栈

12、:UCHAR MajorFunction指示IRP_MJ_XXX派遣例程UCHAR MinorFunction同上,一般文件系统和SCSI驱动程序使用它union ParametersMajorFunction 的联合类型struct ReadIRP_MJ_READ 的参数ULONG LengthULONG KeyLARGE_INTEGER ByteOffsetstruct Write IRP_MJ_WRITE 的参数ULONG LengthULONG KeyLARGE_INTEGER ByteOffsetstruct DeviceIoControl IRP_MJ_DEVICE_CONTROL

13、 参数ULONG OutputBufferLengthULONG InputBufferLengthULONG IoControlCodePVOID Type3InputBufferPDEVICE_OBJECT DeviceObject请求的目标设备对象的指针PFILE_OBJECT FileObject请求的目标文件对象的指针IRP 的创建:由系统的 IO 请求创建,也可以在驱动程序中自己创建。 IoBuildAsynchronousFsdRequest创建异步IRP(不需要等待其完成)。该函数和下一个函数仅适用于创建某些类型的 IRP。 IoBuildSynchronousFsdReque

14、st 创建同步 IRP(需要等待其完成)。 IoBuildDeviceloControlRequest 创建一个同步 IRP_MJ_DEVICE_CONTROL 或IRP_MJ_INTERNAL_DEVICE_CONTROL 请求。IoAllocateIrp 创建上面三个函数不支持的其它种类的 IRP。IRP 的处理流程:IRP创建好之后被发往派遣例程,我们在相应的派遣例程中处理IRP,在前面的DriverDispatchXXX已经描 述过了。IRP 的完成:派遣函数也可以在下面这两种情况下完成 IRP: 如果请求是错误的,则派遣例程应以失败方式完成该请求并返回适当的出错代码。 如果请求要求得

15、到的仅是派遣函数可以容易确定的信息(比如说打印一些信息,进行一些IO操作), 则派遣例程应立即给出回答并完成请求,返回成功状态码。完成一个IRP必须先填充IoStatus块的Status和Information成员,然后调用IoCompleteRequest()例程。Status值就是NTSTATUS.H中定义的状态代码。而Information值要取决于你完成的是何种 类型的IRP以及是成功还是失败。通常情况下,如果IRP完成失败(即,完成的结果是某种错误状态),你 应把Information域置0。如果你成功地完成了一个数据传输IRP,通常应该把Information域设置成 传输的字节量。当 IoCompleteReques 返回代码是除了 STATUS_MORE_PROCESSING_REQUIRED 以外的其它值,它就 把堆栈指针移动到上一层并重复前面的工作。如果返回代码是STATUS_MORE_PROCESSING_REQUIRED, IoCompleteRequest将停止前进并返回到调用者,而此时的IRP将处于一个中间状态。完成例程在下面情况下会调用 IoMarkIrpPending ():如果完成例程将以 STATUS_PE

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文 > 其它学术论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号