Prerequisite for understanding this chapter is to understand the Driver and the Device object stack in the Windows Operating System. Please read the blog (Device Object and Driver Stack (Part 1).
In this blog we start with understanding the Windows IO Model. Then we proceed to discuss some more detail about the I/O system and how it interacts with the layered driver structure to service a request. Request is created by a client (can be application, any kernel subsystem like PnP manager or another driver) and is processed by the destined driver. We will see that these requests are represented as packets, aptly called I/O request Packets (IRPs). Finally we brief about how the IO moves from an application through the system and the device stack to complete this IO Request.
In the next blog we will take a look at the code and the structures that are associated with what has been discussed in last two chapters.
The Windows I/O Model
The Windows I/O model governs how the data flows to and from the peripheral device. The model encompasses more than just data transfers to and from a device - it operates as a general packet based mechanism that handles the communication between the clients who issue the request and the device stack. Clients include the applications, kernel subsystems such as the PnP manager, and the drivers themselves.
All I/O requests to drivers sent as I/O request packets (IRPs). In addition to the data transfer (Read, Write, Control), IRPs are also used to carry Plug and Play requests, power management requests, WMI requests, notifications of change in device status, and queries about device and driver resources.
Application typically access the drivers synchronously. From the perspective of the driver, however, Windows I/O is inherently asynchronous. Example, if read operation takes time, the drivers starts the necessary operation and informs the I/O manager that the request is pending. In the interim, the driver is free to process additional requests.
For synchronous application, I/O manager simply waits until the driver finishes the read operation before returning the data to the application.
For asynchronous application, when the driver informs the I/O manager that the request is pending, the I/O manager informs the application and returns the thread to the application's control. While the request is being satisfied, the application can then use the thread for other purposes.
Eventually, the device signals the driver that the read operation is complete. The driver informs the I/O manager, which notifies the application, and the application can then process the data.
The I/O manager defines a set of standard routines, some required and other optional, that drivers can support. All drivers follow a relatively consistent implementation model, given the differences among the peripheral devices and differing functionality required of bus, function, filter and file system drivers.
I/O manager has been briefly described in the Kernel subsystems section in the blog: (Windows Driver Fundamentals)
I/O system defines the orderly framework or model within which I/O are delivered to device drivers. As mentioned earlier, I/Os are represented by an I/O request packet (IRP), which travels from one I/O system component to another.
An IRP is a data structure that contains information completely describing an I/O request. The I/O manager creates an IRP in the memory to represent an I/O operation, passing a pointer to the IRP to the correct driver and disposing of the packet when the I/O operation is complete.
A driver receives an IRP, performs the operation the IRP specifies, and passes the IRP back to the I/O manager, either because the requested I/O operation has been completed, or because it must be passed to the another driver for further processing.
In addition to creating and disposing all the IRPs, the I/O manager supplies code that is common to different drivers and that the drivers can call to carry out their I/O processing. By consolidating common tasks in the I/O manager, individual drivers becomes more simpler and more compact.
I/O manager also manages buffer for the I/O requests, provides timeout support for the drivers, and records which installable file systems are loaded into the operating system.
The uniform modular interface that the driver presents allows the I/O manager to call any driver without requiring any special knowledge of its structure or internal details.
Drivers can also call each other (using I/O manager) to achieve layered, independent processing of an I/O request.
I/O Requests (IRPs)
The following are the most common types of the I/O requests issued from the application:
Write Requests: These requests pass data to the driver to be written to the device.
Read Requests: These requests pass a buffer to the driver to be filled with data from the device.
Device I/O control requests: These requests are used to communicate with drivers for any purposes other than reading or writing data. For some device, I/O control requests are the most common request type.
We will examine the IRPs including different I/O transfer types in details in the upcoming blogs. For now, this general information will suffice for understanding.
How a Device Stack Handles IRPs.
When a client sends an I/O request to a device, the I/O manager packages the request and related information such as data buffers into an IRP. The I/O manager locates the pointer to the appropriate dispatch routine in the top device object in the stack and calls the routine and passes the IRP to the associated driver for processing.
path that an I/O request follows from an application through the system and the device stack. Once we discuss the IRPs in detail in later blogs, we will discuss in detail about the processing of IRPs through the KMDF drivers.
I/O request Flow:Follow the figure 1.
An application issues an I/O request by calling a Windows API function.
The Windows API calls the kernel mode subsystems which call the corresponding I/O processing function of the I/O manager.
The I/O manager builds an IRP that describes the I/O request and sends it to the top driver in the kernel mode device stack for the target device.
If the IRP is not complete, the kernel mode driver sends it to the next lower driver in the device stack. The driver processes the IRP and, in turn, sends it to the next lower driver and so on down the device stack, until a driver completes the IRP.
Any driver that sends an IRP down the stack can register an I/O completion callback to have the opportunity to process the IRP again after lower drivers have completed it.
Finally, the IRP reaches a driver that completes it.
After the IRP is complete, the I/O manager calls the I/O completion callbacks that drivers set as the request passed down the device stack, in reverse order.
The driver that completes the IRP doesn't require an I/O completion callback because it already knows that the request is complete and has completed its processing.
The I/O manager retrieves the I/O status from the IRP, translates the status to a Windows error code, returns completion information and, if necessary, copies data to the requesting application's data buffer.
The I/O manager then returns control to the Windows API.
The Windows API returns the results of the operation to the requesting application.
ReferencesI am following the given resources:
Windows Driver Foundation resource on MSDN.
Windows Internals by by Russinovich, Solomon, and Ionescu (6th Edition).
Developing Drivers with the Windows Driver Foundation by Penny Orwick and Guy Smith.
OSR Online site which is a must visit for every Windows Driver Developer and has everything related to writing, testing and maintaining Windows Drivers.