I/O Request Packet(IRP)
IRP概述:
IRP是由I/O管理器发出的,I/O管理器是用户态与内核态之间的桥梁,当用户态进程发出I/O请求时,I/O管理器就捕获这些请求,将其转换为IRP请求,发送给驱动程序。
I/O管理器无疑是非常重要的,具有核心地位。它负责所有I/O请求的调度和管理工作,根据请求的不同内容,选择相应的驱动程序对象,设备对象,并生成、发送、释放各种不同的IRP。
整个I/O处理流程是在它的指挥下完成的。
一个IRP是从非分页内存中分配的可变大小的结构,它包括两部分:IRP首部和I/O堆栈。
IRP首部中包含了指向IRP输入输出缓冲区指针、当前拥有IRP的驱动指针等。
紧接着首部的IO_STACK_LOCATION结构的数组。它的大小由设备栈中的设备数确定。IO_STACK_LOCATION结构中保存了一个I/O请求的参数及代码、请求当前对应的设备指针、完成函数指针(IoCompletion)等。
IRP结构介绍:
我们先看看WRK中对IRP的定义
1 typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP { 2 CSHORT Type; 3 USHORT Size; 4 5 // 6 // Define the common fields used to control the IRP. 7 // 8 9 // 10 // Define a pointer to the Memory Descriptor List (MDL) for this I/O 11 // request. This field is only used if the I/O is "direct I/O". 12 // 13 14 PMDL MdlAddress; 15 16 // 17 // Flags word - used to remember various flags. 18 // 19 20 ULONG Flags; 21 22 // 23 // The following union is used for one of three purposes: 24 // 25 // 1. This IRP is an associated IRP. The field is a pointer to a master 26 // IRP. 27 // 28 // 2. This is the master IRP. The field is the count of the number of 29 // IRPs which must complete (associated IRPs) before the master can 30 // complete. 31 // 32 // 3. This operation is being buffered and the field is the address of 33 // the system space buffer. 34 // 35 36 union { 37 struct _IRP *MasterIrp; 38 __volatile LONG IrpCount; 39 PVOID SystemBuffer; 40 } AssociatedIrp; 41 42 // 43 // Thread list entry - allows queueing the IRP to the thread pending I/O 44 // request packet list. 45 // 46 47 LIST_ENTRY ThreadListEntry; 48 49 // 50 // I/O status - final status of operation. 51 // 52 53 IO_STATUS_BLOCK IoStatus; 54 55 // 56 // Requestor mode - mode of the original requestor of this operation. 57 // 58 59 KPROCESSOR_MODE RequestorMode; 60 61 // 62 // Pending returned - TRUE if pending was initially returned as the 63 // status for this packet. 64 // 65 66 BOOLEAN PendingReturned; 67 68 // 69 // Stack state information. 70 // 71 72 CHAR StackCount; 73 CHAR CurrentLocation; 74 75 // 76 // Cancel - packet has been canceled. 77 // 78 79 BOOLEAN Cancel; 80 81 // 82 // Cancel Irql - Irql at which the cancel spinlock was acquired. 83 // 84 85 KIRQL CancelIrql; 86 87 // 88 // ApcEnvironment - Used to save the APC environment at the time that the 89 // packet was initialized. 90 // 91 92 CCHAR ApcEnvironment; 93 94 // 95 // Allocation control flags. 96 // 97 98 UCHAR AllocationFlags; 99 100 // 101 // User parameters. 102 // 103 104 PIO_STATUS_BLOCK UserIosb; 105 PKEVENT UserEvent; 106 union { 107 struct { 108 union { 109 PIO_APC_ROUTINE UserApcRoutine; 110 PVOID IssuingProcess; 111 }; 112 PVOID UserApcContext; 113 } AsynchronousParameters; 114 LARGE_INTEGER AllocationSize; 115 } Overlay; 116 117 // 118 // CancelRoutine - Used to contain the address of a cancel routine supplied 119 // by a device driver when the IRP is in a cancelable state. 120 // 121 122 __volatile PDRIVER_CANCEL CancelRoutine; 123 124 // 125 // Note that the UserBuffer parameter is outside of the stack so that I/O 126 // completion can copy data back into the user's address space without 127 // having to know exactly which service was being invoked. The length 128 // of the copy is stored in the second half of the I/O status block. If 129 // the UserBuffer field is NULL, then no copy is performed. 130 // 131 132 PVOID UserBuffer; 133 134 // 135 // Kernel structures 136 // 137 // The following section contains kernel structures which the IRP needs 138 // in order to place various work information in kernel controller system 139 // queues. Because the size and alignment cannot be controlled, they are 140 // placed here at the end so they just hang off and do not affect the 141 // alignment of other fields in the IRP. 142 // 143 144 union { 145 146 struct { 147 148 union { 149 150 // 151 // DeviceQueueEntry - The device queue entry field is used to 152 // queue the IRP to the device driver device queue. 153 // 154 155 KDEVICE_QUEUE_ENTRY DeviceQueueEntry; 156 157 struct { 158 159 // 160 // The following are available to the driver to use in 161 // whatever manner is desired, while the driver owns the 162 // packet. 163 // 164 165 PVOID DriverContext[4]; 166 167 } ; 168 169 } ; 170 171 // 172 // Thread - pointer to caller's Thread Control Block. 173 // 174 175 PETHREAD Thread; 176 177 // 178 // Auxiliary buffer - pointer to any auxiliary buffer that is 179 // required to pass information to a driver that is not contained 180 // in a normal buffer. 181 // 182 183 PCHAR AuxiliaryBuffer; 184 185 // 186 // The following unnamed structure must be exactly identical 187 // to the unnamed structure used in the minipacket header used 188 // for completion queue entries. 189 // 190 191 struct { 192 193 // 194 // List entry - used to queue the packet to completion queue, among 195 // others. 196 // 197 198 LIST_ENTRY ListEntry; 199 200 union { 201 202 // 203 // Current stack location - contains a pointer to the current 204 // IO_STACK_LOCATION structure in the IRP stack. This field 205 // should never be directly accessed by drivers. They should 206 // use the standard functions. 207 // 208 209 struct _IO_STACK_LOCATION *CurrentStackLocation; 210 211 // 212 // Minipacket type. 213 // 214 215 ULONG PacketType; 216 }; 217 }; 218 219 // 220 // Original file object - pointer to the original file object 221 // that was used to open the file. This field is owned by the 222 // I/O system and should not be used by any other drivers. 223 // 224 225 PFILE_OBJECT OriginalFileObject; 226 227 } Overlay; 228 229 // 230 // APC - This APC control block is used for the special kernel APC as 231 // well as for the caller's APC, if one was specified in the original 232 // argument list. If so, then the APC is reused for the normal APC for 233 // whatever mode the caller was in and the "special" routine that is 234 // invoked before the APC gets control simply deallocates the IRP. 235 // 236 237 KAPC Apc; 238 239 // 240 // CompletionKey - This is the key that is used to distinguish 241 // individual I/O operations initiated on a single file handle. 242 // 243 244 PVOID CompletionKey; 245 246 } Tail; 247 248 } IRP;