Sei sulla pagina 1di 7

This article gives a high-level understanding of the I/O concepts as defined in the Windows Driver Model.

It assumes knowledge of basic WDM Concepts.

I/O Flow through Device Stack Driver contains a collection of routines that can be called by the I/O Manager. The I/O Manager typically calls a driver routine at the following conditions: i. When a driver is loaded ii. When a driver is unloaded or the system is shutting down iii. When a device is inserted or removed iv. When a user-mode program issues an I/O request (which is routed through the device object) v. When a shared hardware resource becomes available for driver use I/O request packets (IRPs) are kernel mode structures that are used to facilitate communication between each of the WDM drivers as well as when the operating system needs to communicate with the drivers. Life-cycle of IRP: I. With each user-mode request for I/O, the I/O Manager allocates an IRP from nonpaged system memory. The I/O Manager is responsible to pass the IRP to the appropriate driver. II. When the operation is complete, the driver stores a final status code in the IRP and returns it to the I/O Manager. III. The I/O Manager uses the information in the IRP to complete the request and send the user the final status.

I/O stack location(s) The I/O manager gives each driver in a chain of layered drivers an I/O stack location for every IRP that it sets up. Each I/O stack location consists of an IO_STACK_LOCATION structure. Each stack location corresponds to a particular driver in the chain of layered drivers. The lowest-level driver in a chain of layered drivers can safely access only its own I/O stack location in any IRP. A higher-level driver in a chain of layered drivers can safely access only its own and the next-lower-level driver's I/O stack locations in any IRP. Such a driver must set up the I/O stack location for the next-lower-level driver in IRPs. However, when designing a higher-level driver, you cannot predict when (or whether) a new driver will be added to the current format of chain just below your driver. However we can safely assume that any subsequently added (intermediate) driver will handle the same IRP major function codes (IRP_MJ_XXX) as the displaced next-lower-level driver did.

Structure of an I/O Request Packet (IRP)


An I/O status block provides the higher-level driver (in driver chain) a way of determining whether or not the service worked when the IRP is completed. The Status field indicates whether the drivers that processed the IRP actually completed the request or failed the IRP. The Information field supplies the caller with more information about what actually occurred. For example, it contains the number of bytes actually transferred after a read or write operation. Each driver-specific I/O stack location in an IRP contains the following general information: 1) The major function code (IRP_MJ_XXX), indicating the basic operation the driver should carry out. These include IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL. 2) For some major function codes we need an additional minor function code (IRP_MN_XXX), indicating which sub-case of the basic operation the driver should carry out. 3) A set of operation-specific arguments, such as the length and starting location of a buffer into which or from which the driver transfers data. The format of the parameter section varies according to the Major and/or Minor code being handled. 4) A pointer to the driver-created device object, representing the target device for the requested operation 5) File system driver accesses the file object, to get a pointer to the file object, representing an open file, device, directory, or volume. Other drivers usually ignore the file object.

Layered Processing of IO_Stack_Location (within a Dispatch Routine)


Passing down the IRP 1) Call IoGetCurrentIrpStackLocation to get a pointer to its own I/O stack location. 2) Call IoGetNextIrpStackLocation to retrieve a pointer to the I/O stack location of the next lower driver. 3) Set up the next lower driver's I/O stack location, including the MajorFunction field and various members of the Parameters union. 4) Call IoSetCompletionRoutine to associate an I/O Completion routine with the IRP. 5) Send the IRP to a lower-level driver using IoCallDriver. 6) Return the status code that is returned by IoCallDriver which is either a STATUS_SUCCESS, STATUS_PENDING or some STATUS_XXX error code. Completing the IRP 1) Call IoGetCurrentStackLocation to get a pointer to the driver's I/O stack slot. 2) Process the request using various fields in the IRP and the I/O stack location. 3) Put an appropriate value in the IoStatus.Information field of the IRP. 4) Fill the IoStatus.Status field of the IRP with a suitable STATUS_XXX code. 5) Call IoCompleteRequest to send the IRP back to the I/O Manager. 6) Return the same STATUS_XXX code that it puts into the IRP.

Layered Processing of IRP


Since layered drivers do not directly manage hardware, they do not need Start I/O, Interrupt Service, or DPC routines. Instead, most of the code in a layered driver consists of Dispatch routines and I/O Completion routines. When one of these Dispatch routines receives an IRP, one of three actions can be taken: Complete the IRP Pass down the IRP Generate new IRP requests for lower layers.