Monday, May 8, 2017

Windows I/O Model

A prerequisite for understanding this chapter is understanding the Driver and the Device object stack in the Windows Operating System. Please refer to the blog (Device Object and Driver Stack (Part 1).
In this blog, we start with understanding the Windows IO Model. Subsequently, we discuss the I/O system and its interaction with the layered driver structure to service a request. A client creates the request (can be an application, any kernel subsystem like PnP manager or another driver), and the destined Driver processes them. Kernel subsystems structure these requests into packets, aptly called I/O Request Packets (IRPs). Finally, we brief how the IO moves from an application through the system and the device stack to completion.

In the next blog, we will look at the associated code and the structures.

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 - 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.


All I/O requests to drivers are 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.


An application typically accesses the drivers synchronously. From the Driver's perspective, however, Windows I/O is inherently asynchronous. For example, if the read operation takes time, the Driver starts the necessary procedure and informs the I/O manager that the request is pending. In the interim, the Driver is free to process additional requests.

For synchronous operation, the I/O manager waits until the Driver finishes the read operation before returning the data to the application.

For an asynchronous operation, 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 satisfied, the application can 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 others 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

The kernel subsystems section in the blog briefly described the I/O manager: (Windows Driver Fundamentals)

I/O system defines the orderly framework or model within which I/O are delivered to the device drivers. As mentioned earlier, I/Os are represented by an I/O request packet (IRP), travelling from one I/O system component to another.

An IRP is a data structure that contains information 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 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 is complete or because it must pass to another driver for further processing.

In addition to creating and disposing of all the IRPs, the I/O manager supplies code common to different drivers that the drivers can call to carry out their I/O processing. By consolidating common tasks in the I/O manager, individual drivers become simpler and more compact.

I/O manager also manages buffer for the I/O requests, provides timeout support for the drivers and records installable file systems loaded into the operating system.

The uniform modular interface that the Driver presents allows the I/O manager to call any driver without requiring special knowledge of its structure or internal details.

Drivers can also call each other (using an I/O manager) to achieve layered, independent processing of an I/O request.t.

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 that must write to the device.
  • Read Requests: These requests pass a buffer to the Driver to read and fill the 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 devices, I/O control requests are the most common request type
The standard Windows functions that applications use to issue these I/O requests are WriteFile, ReadFile, and DeviceIoControl respectively.
We will examine the IRPs, including different I/O transfer types, in detail 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 stack's top device object, calls the routine, and passes the IRP to the associated Driver for processing.



Let us see the general 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 the processing of IRPs through the KMDF drivers.

I/O request Flow:

Follow figure 1.
  1. An application issues an I/O request by calling a Windows API function.
  2. The Windows API calls the kernel-mode subsystems, which call the corresponding I/O processing function of the I/O manager.
  3. 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.
  4. 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.
  5. 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.
  6. Finally, the IRP reaches a driver that completes it.
  7. 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.
  8. 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.
  9. The I/O manager retrieves the I/O status from the IRP, translates the status to a Windows error code, returns completion information, and copies data to the requesting application's data buffer.
  10. The I/O manager then returns control to the Windows API.
  11. The Windows API returns the results of the operation to the requesting application.

References

I am following the given resources: