Buffered I/O The I/O manager allocates a buffer in nonpaged pool of equal size to the caller’s buffer. For write operations, the I/O manager copies the caller’s buffer data into the allocated buffer when creating the IRP. For read operations, the I/O manager copies data from the allocated buffer to the user’s buffer when the IRP completes and then frees the allocated buffer. The nonpaged pool buffer is pointed to by the IRP’s
Direct I/O When the I/O manager creates the IRP, it locks the user’s buffer into memory (that is, makes it nonpaged). When the I/O manager has finished using the IRP, it unlocks the buffer. The I/O manager stores a description of the memory in the form of a
Neither I/O The I/O manager doesn’t perform any buffer management. Instead, buffer management is left to the discretion of the device driver, which can choose to manually perform the steps the I/O manager performs with the other buffer management types.
For each type of buffer management, the I/O manager places applicable references in the IRP to the locations of the input and output buffers. The type of buffer management the I/O manager performs depends on the type of buffer management a driver requests for each type of operation. A driver registers the type of buffer management it desires for read and write operations in the device object that represents the device. Device I/O control operations (those requested by calling
Drivers commonly use buffered I/O when callers transfer requests smaller than one page (4 KB on x86 processors) or when the device does not support DMA. They use direct I/O for larger requests on DMA-aware devices. File system drivers commonly use neither I/O because no buffer management overhead is incurred when data can be copied from the file system cache into the caller’s original buffer. The reason that most drivers don’t use neither I/O is that a pointer to a caller’s buffer is valid only while a thread of the caller’s process is executing.
Drivers that use neither I/O to access buffers that might be located in user space must take special care to ensure that buffer addresses are both valid and do not reference kernel-mode memory. Scalar values, however, are perfectly safe to pass, although a few drivers have only a scalar value to pass around. Failure to do so could result in crashes or in security vulnerabilities, where applications have access to kernel-mode memory or can inject code into the kernel. The
I/O Request to a Single-Layered Driver
This section traces a synchronous I/O request to a single-layered kernel-mode device driver. In its most simplified form, handling a synchronous I/O to a single-layered driver consists of seven steps:
The I/O request passes through a subsystem DLL.
The subsystem DLL calls the I/O manager’s
The I/O manager allocates an IRP describing the request and sends it to the driver (a device driver in this case) by calling its own
The driver transfers the data in the IRP to the device and starts the I/O operation.
The device signals I/O completion by interrupting the CPU.
The device driver services the interrupt.
The driver calls the I/O manager’s