Windows Kernel I/O System and Drivers

The I/O system in Windows is a complex and hierarchical structure responsible for managing all input and output operations between applications and hardware devices. It is built around a layered driver model, providing a consistent interface for applications to interact with diverse hardware.

Core Components

The I/O system comprises several key components:

Driver Model

Windows employs a layered driver model, where drivers are stacked on top of each other. This allows for:

Common driver types include:

I/O Request Packets (IRPs)

Communication within the I/O system is primarily done through I/O Request Packets (IRPs). An IRP is a data structure that encapsulates an I/O request from an application or another driver. It contains information such as:

The I/O Manager creates an IRP and passes it down the driver stack. Each driver processes the IRP and can either complete the request, pass it to the driver below it, or create new IRPs.

Example: Reading from a Disk Device

When an application requests to read data from a file:

  1. The I/O Manager receives the request and creates an IRP.
  2. The IRP is passed to the file system driver (e.g., NTFS).
  3. The file system driver determines which physical blocks on the disk correspond to the requested file data and creates a new IRP for the disk class driver.
  4. The disk class driver may further break down the request and pass it to the specific disk controller driver.
  5. The disk controller driver translates the request into commands for the hardware.
  6. As the I/O operation completes, status information and data are passed back up the driver stack via the IRP's completion routine.
Tip: Understanding the IRP structure and the flow of control is crucial for effective driver development and debugging.

Key Concepts

// Simplified conceptual structure of a driver's dispatch routine NTSTATUS DriverDispatchRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { // Extract Major Function Code from IRP PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); ULONG majorFunction = irpSp->MajorFunction; switch (majorFunction) { case IRP_MJ_READ: // Handle read request return IoCompleteRequest(Irp, STATUS_SUCCESS); case IRP_MJ_WRITE: // Handle write request return IoCompleteRequest(Irp, STATUS_SUCCESS); case IRP_MJ_DEVICE_CONTROL: // Handle device control request return IoCompleteRequest(Irp, STATUS_SUCCESS); default: // Pass to next driver or complete with invalid status return IoSkipCurrentIrpStackLocation(Irp); } }

Further Reading