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;
View Code

相关文章: