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函數得到
