SCSI bus, IDE disk controller, PCI bus, expansion bus
Memory, cache, bridge/controller devices
Parallel and serial ports
Buses and controllers provide the bridge between devices and the kernel via device controllers and drivers.
I/O Port Registers
Data-in register: read by the host to get input.
Data-out register: written by the host to send output.
Status register: contains bits read by the host indicating device state.
Bits indicate: whether the current command has completed, whether a byte is available to be read from the data-in register, and whether a device error has occurred.
Control register: written by the host to start a command or to change the mode of a device.
Polling
Step-by-step polling sequence to perform I/O:
Step 1: The host repeatedly reads the busy bit until that bit becomes clear.
Step 2: The host sets the write bit in the command register and writes a byte into the data-out register.
Step 3: The host sets the command-ready bit.
Step 4: When the controller notices that the command-ready bit is set, it sets the busy bit.
Step 5: The controller reads the command register and sees the write command. It reads the data-out register to get the byte and does the I/O to the device.
Step 6: The controller clears the command-ready bit, clears the error bit in the status register to indicate that the device I/O succeeded, and clears the busy bit to indicate that it is finished.
Interrupts
It is more efficient to arrange for the hardware controller to notify the CPU when the device becomes ready for service, instead of polling continuously.
The hardware mechanism that enables a device to notify the CPU is called an interrupt.
The CPU hardware has a wire called the interrupt-request line that the CPU senses after executing every instruction.
Interrupt-driven I/O (Flow)
CPU, I/O controller, and device driver participate in interrupt-driven I/O:
The device driver initiates I/O on a device.
CPU executes and checks for interrupts between instructions.
When an interrupt occurs, the CPU transfers control to an interrupt handler.
The interrupt handler processes data and returns from the interrupt.
CPU resumes processing of the interrupted task.
The interrupt indicates that input is ready, output is complete, or an error occurred.
Direct Memory Access (DMA)
Used to avoid programmed I/O (one byte at a time) for large data movement.
Requires a DMA controller.
Bypasses CPU to transfer data directly between I/O device and memory.
OS writes a DMA command block into memory containing:
Source and destination addresses
Read or write mode
Count of bytes
Writes location of the command block to the DMA controller.
Bus mastering of the DMA controller – grabs the bus from the CPU.
Cycle stealing from the CPU but still much more efficient overall.
When done, interrupts to signal completion.
A version aware of virtual addresses (DVMA) can be even more efficient.
Six Step Process to Perform DMA Transfer
The following steps describe the DMA transfer process (illustrative):
Step 1: Device driver is told to transfer disk data to buffer at address X.
Step 2: Device driver tells disk controller to transfer C bytes from disk to buffer at address X.
Step 3: Disk controller initiates DMA transfer.
Step 4: Disk controller sends each byte to the DMA controller.
Step 5: DMA controller transfers bytes to buffer, increasing memory address and decreasing C until C = 0.
Step 6: When C = 0, DMA interrupts CPU to signal transfer completion.
Context sketch includes PCI/IDE bus, memory buffer, and the memory bus involved in the transfer.
Application I/O Interface
I/O system calls encapsulate device behaviors in generic classes.
The device-driver layer hides differences among I/O controllers from the kernel.
New devices communicating already-implemented protocols require no extra work.
Each OS has its own I/O subsystem structures and device-driver frameworks.
Devices vary in several dimensions:
Character-stream vs block
Sequential vs random-access
Synchronous vs asynchronous (or both)
Sharable vs dedicated
Speed of operation
Read-write, read-only, or write-only
Kernel I/O Structure
Hardware and software responsibilities shape the kernel I/O structure.
Examples of device mappings include:
SCSI keyboard and mouse
SCSI disk devices and controllers
PCI bus devices and ATAPI (e.g., floppy, disk)
Bus bridges and memory controllers
The kernel I/O subsystem interfaces with hardware through device drivers and the kernel I/O subsystem.
Keyboard, mouse, disk, and other devices are connected via appropriate buses and controllers (SCSI, PCI, ATAPI).
Kernel I/O Subsystem
Kernels provide services related to I/O: scheduling, buffering, caching, spooling, device reservation, and error handling.
I/O Scheduling:
Maintains a wait queue of requests for each device.
When an application issues a blocking I/O system call, the request is placed on the queue for that device.
The I/O scheduler rearranges the order of the queue to improve overall system efficiency and average response time for applications.
Maintaining a device-status table.
Kernel I/O Subsystem (Device Status Example)
Example device statuses:
device: keyboard, status: idle
device: laser printer, status: busy
device: mouse, status: idle
device: disk unit 1, status: idle
device: disk unit 2, status: busy
Example requests:
request for laser printer: address 38546, length 1372
request for disk unit 2: file: xxx, operation: read, address 43046, length 20000
request for disk unit 2: file: yyy, operation: write, address 03458, length 500
Buffering, Caching, Spooling, and Copy Semantics
Buffering: cope with speed mismatch between producer and consumer of a data stream; accommodate different data-transfer sizes; support copy semantics for application I/O.
Copy semantics: the version of data written to disk is guaranteed to be the version at the time of the application system call, independent of subsequent changes in the application’s buffer.
Caching: a region of fast memory that holds copies of data; a buffer may hold the only existing copy of a data item whereas a cache holds a copy on faster storage of an item that resides elsewhere.
Spooling and Device Reservation
A spool is a buffer that holds output for a device (e.g., a printer) that cannot accept interleaved data streams.
Managed by a system daemon process or an in-kernel thread.
The OS provides a control interface to display queue, remove unwanted jobs, suspend printing, etc.
Error Handling
An OS using protected memory guards against many kinds of hardware and application errors.
I/O transfers can fail for transient reasons (e.g., network overload) or permanent reasons (e.g., defective disk controller).
An I/O system call will return one bit of information about the status of the call.
I/O Protection
A user process may attempt to issue illegal I/O instructions.
All I/O instructions are defined as privileged instructions and must be performed through the OS.
The OS, executing in monitor mode, checks that the request is valid.
Any memory-mapped and I/O port memory locations must be protected from user access by the memory-protection system.
Kernel Data Structures
The kernel maintains state information about I/O component usage:
Open file table
Tracked network connections
Character-device communications
Other I/O activities
I/O Request Processing (End-to-End Flow)
A user process issues an I/O request via a system call.
The kernel I/O subsystem determines if it can satisfy the request internally.
If yes: send the request to the device driver and potentially block the process.
If no: process the request, issue commands to the controller, and configure the controller to block until interrupted.
Device driver and I/O controller handle the actual transfer.
An interrupt indicates completion; the interrupt handler stores data in the device-driver buffer.
If input is involved, the process is unblocked; the kernel monitors device status and interrupts when I/O completes.
The I/O subsystem determines which I/O completed and updates state accordingly.
The final interrupt signals completion, and the I/O operation results are returned to the originating process.
I/O Diagram Summary (Page 18 Flow)
The sequence illustrates: user process -> system call -> kernel I/O subsystem -> device driver -> device controller -> interrupts -> interrupt handler -> data transfer -> completion notification -> process unblocked or completed