Windows驱动开发-IRP结构体
IRP的全名是I/O Request Package,即输入输出请求包,它是Windows内核中的一种非常重要的数据结构。
上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求,操作系统将相应的I/O请求转换成相应的IRP,不同的IRP会根据类型被分派到不同的派遣例程中进行处理。
IRP有两个基本的属性,即MajorFunction和MinorFunction,分别记录IRP的主类型和子类型。
操作系统根据MajorFunction决定将IRP分发到哪个派遣例程,然后派遣例程根据MinorFunction进行细分处理。
没有设置派遣函数的IRP,默认与IopInvalidDeviceRequest函数关联
IRP结构体源码
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP { CSHORT Type; USHORT Size; PMDL MdlAddress; ULONG Flags; union { struct _IRP *MasterIrp; __volatile LONG IrpCount; PVOID SystemBuffer; } AssociatedIrp; LIST_ENTRY ThreadListEntry; IO_STATUS_BLOCK IoStatus; KPROCESSOR_MODE RequestorMode; BOOLEAN PendingReturned; CHAR StackCount; CHAR CurrentLocation; BOOLEAN Cancel; KIRQL CancelIrql; CCHAR ApcEnvironment; UCHAR AllocationFlags; PIO_STATUS_BLOCK UserIosb; PKEVENT UserEvent; union { struct { union { PIO_APC_ROUTINE UserApcRoutine; PVOID IssuingProcess; }; PVOID UserApcContext; } AsynchronousParameters; LARGE_INTEGER AllocationSize; } Overlay; __volatile PDRIVER_CANCEL CancelRoutine; PVOID UserBuffer; union { struct { union { KDEVICE_QUEUE_ENTRY DeviceQueueEntry; struct { PVOID DriverContext[4]; } ; } ; PETHREAD Thread; PCHAR AuxiliaryBuffer; struct { LIST_ENTRY ListEntry; union { struct _IO_STACK_LOCATION *CurrentStackLocation; ULONG PacketType; }; }; PFILE_OBJECT OriginalFileObject; } Overlay; KAPC Apc; PVOID CompletionKey; } Tail; } IRP;
驱动程序会创建一个个的设备对象,并将这些设备对象“叠”成一个垂直结构,这种垂直的结构很像栈,因此叫做“设备栈”
IRP会被操作系统发送到设备栈的顶层,如果顶层的设备对象的派遣函数结束了IRP的请求,则这次I/O请求结束,如果没有
将IRP请求结束,那么操作系统将IRP转发到设备栈的下一层设备处理,如果这个设备的派遣函数依然不能结束IRP请求,则
会继续向更下层设备转发,
因此,一个IRP请求可能被转发多次,为了记录IRP在每层设备中做的操作,IRP会有个IO_STACK_LOCATION数组,数组的元素个数
应该大于IRP穿过的设备数目,对于本层设备对应的IO_STACK_LOCATION,可以通过IoGetCurrentIrpStackLocation函数得到