I/O Request Packets (IRPs)Almost all I/O under Windows 2000 is packet-driven. Each separate I/O transaction is described by a work order that tells the driver what to do and tracks the progress of the request through the I/O subsystem. These work orders take the form of a data structure called an I/O Request Packet (IRP), and this section describes their use and purpose.
The procedure just described is, in fact, a simplified model of IRP processing. It only applies in a flat driver model. When drivers are layered, one upon the other, the procedure is more complex. A single IRP may travel through several layers of drivers before the request is completed. Additionally, higher-level drivers can create new IRPs and disperse them to other drivers. Layout of an IRPAn IRP is a variable-sized structure allocated from nonpaged pool. Figure 4.1 shows that an IRP has two sections. Figure 4.1. Structure of an IRP.
IRP HEADERThis area of the IRP holds various pieces of information about the overall I/O request. Some parts of the header are directly accessible to the driver, while other pieces are the exclusive property of the I/O Manager. Table 4.1 lists the fields in the header that a driver is allowed to touch. The IoStatus member holds the final status of the I/O operation. When a driver is ready to complete the processing of an IRP, it sets this Status field of this block to a STATUS_XXX value. At the same time, a driver should set the information field of the status block either to 0 (if there is an error) or to a function code-specific value (for example, the number of bytes transferred). The AssociatedIrp.SystemBuffer, MdlAddress, and UserBuffer fields play various roles in managing the driver's access to data buffers. Later chapters explain how to use these fields if a driver performs either Buffered or direct I/O. I/O STACK LOCATIONSThe main purpose of an I/O stack location is to hold function code and parameters of an I/O request. By examining the MajorFunction field of the stack locations, a driver can decide what operation to perform and how to interpret the Parameters union. Table 4.2 describes some of the commonly used members of an I/O stack location. For requests sent directly to a lowest-level driver, the corresponding IRP has only one I/O stack location. For requests sent to a higher-level driver, the I/O Manager creates an IRP with separate I/O stack locations for each driver layer. In other words, the size of an I/O stack is really the number of I/O layers that participate in an I/O request. Every driver in the hierarchy is allowed to touch only its own stack location. If a driver chooses to call a lower-layer driver, it must ensure that a new stack location has been correctly created beneath it.
When a driver passes an IRP to a lower-level driver, the I/O Manager automatically pushes the I/O stack-pointer so that it points at the I/O stack location belonging to the lower driver. When the lower driver releases the IRP, the I/O stack pointer is popped so that it again points to the stack location of the higher driver. Chapter 15 explains in detail how to work with this mechanism. Manipulating IRPsSome IRP access functions operate only on the IRP header. Others deal specifically with the IRP's I/O stack locations. It is important to know whether an access function needs the pointer to the entire IRP or a pointer to an IRP stack location. The following sections describe each group of access functions.
IRPS AS A WHOLEThe I/O Manager exports a variety of functions that work with IRPs. Table 4.3 lists the most common ones. Later chapters explain how to use them. IRP STACK LOCATIONSThe I/O Manager also provides several functions that drivers can use to access an IRP's stack locations. These functions are listed in Table 4. 4.
|