WDM中的结构
---IRP
几乎所有的Windows2000的I/O都是包驱动的,系统采取一种称为“I/O请求包(IRP--I/O request packet)”的数据结构来完成与内核模式驱动程序通信。IRP由I/O管理器根据用户态程序提出的请求创建并传给相应的驱动程序。在分层的驱动程序中,这个过程很复杂,一个IRP常常要穿越几层驱动程序。另外,驱动程序也能够建立新的IRP并传递给其它驱动程序。
IRP功能的复杂性决定了它结构的复杂性,正确的理解IRP的结构是理解WDM框架的基础。IRP由I/O管理器在非分页内存池内创建,它包括两部分:头部区域和I/O堆栈位置。
l IRP头部可见字段
AssociatedIrp.SystemBuffer 设备执行缓冲I/O时,指向系统空间缓冲区
PMDL MdlAddress 设备执行直接I/O时,指向用户空间的内存描述表
IO_STATUS_BLOCK IoStatus 包含了I/O请求的状态;驱动程序在最终完成请求时设置这个结构。IoStatus.Status域将收到一个NTSTATUS代码。
PVOID UserBuffer 对于METHOD_NEITHER方式的
IRP_MJ_DEVICE_CONTROL请求,该域包含输出缓冲区的用户模式虚拟地址。该域还用于保存读写请求缓冲区的用户模式虚拟地址,但指定了DO_BUFFERED_IO或DO_DIRECT_IO标志的驱动程序,其读写例程通常不需要访问这个域。当处理一个METHOD_NEITHER控制操作时,驱动程序能用这个地址创建自己的MDL。
BOOLEAN Cancel 指示IRP已经被取消
l I/O堆栈位置
MajorFunction 指示执行什么I/O操作以及如何解释Parameters 字段
MinorFunction 由文件系统合SCSI驱动程序使用
Parameters MajorFunction代码决定此联合的内容
DeviceObject I/O请求的目标设备
FileObject 请求的文件对象
I/O堆栈位置的主要目的是,保存一个I/O请求的函数代码和参数。而I/O堆栈数量实际上就是参与I/O请求的I/O层的数量。在一个IRP中,上层驱动负责负责为下层驱动设置堆栈位置指针。驱动程序可以为每个IRP调用IoGetCurrentIrpStackLocation来获得指向其自身堆栈位置的指针,而上层驱动程序必须调用IoGetNextIrpStackLocation来获得指向下层驱动程序堆栈位置的指针。因此,上层驱动可以在传送IRP给下层驱动之前设置堆栈位置的内容。
上层驱动调用IoCallDriver,将DeviceObject成员设置成下层驱动目标设备对象。当上层驱动完成IRP时,IoCompletion 函数被调用,I/O管理器传送给IoCompletion函数一个指向上层驱动的设备对象的指针。