ยง36.1โ€“36.3System Architecture โ€ฆ The Canonical Protocol

Part III OSTEP pp. 419โ€“422 ยท ~5 min read

  • bus
  • firmware
  • device register
  • polling
  • programmed i/o

Before persistence proper, we need the thing that stores it: the input/output device. A program with no input is boring; one with no output is pointless. So โ€” how does the OS talk to hardware?

The Crux: How To Integrate I/O Into Systems

How should I/O be integrated into systems? What are the general mechanisms, and how can we make them efficient?

36.1 System Architecture

Devices donโ€™t all hang off one wire โ€” they attach through a hierarchy of buses , fastest nearest the CPU:

Figure 36.1: the bus hierarchy. Fast, short, expensive buses sit near the CPU; slow, cheap buses hold many devices further out.

CPUMemorymemory busGeneral I/O Bus (e.g., PCIe)Graphics ยท NVMePeripheral Bus (e.g., SATA, USB)Disk ๐Ÿ’พKeyboardMousefaster ยท shorter ยท costlier (near CPU) โ†’ slower ยท cheaper ยท more devices

Why a hierarchy? Physics and cost. A faster bus must be shorter (so it canโ€™t fit many plugs) and is expensive to engineer โ€” so high-performance parts (graphics, NVMe) go near the CPU, while slow devices (disks, keyboard, mouse) share a cheap peripheral bus that can hold many of them.

36.2 A Canonical Device

Every device has two parts: a hardware interface it presents to the system, and its internal structure (implementation). Simple devices use a few chips; complex ones pack a micro-controller, memory, and sometimes hundreds of thousands of lines of firmware (software inside the hardware โ€” e.g. a RAID controller):

Figure 36.3: a canonical device โ€” a register interface on top, hidden internals below.

registers (the interface)StatusCommandDataInterfaceinternals (implementation-specific)โ€ข Micro-controller (a small CPU)โ€ข Memory (DRAM / SRAM) ยท firmwareโ€ข Other hardware-specific chipsInternals

36.3 The Canonical Protocol

The interface is three device registers : STATUS (read the deviceโ€™s state), COMMAND (tell it to do a task), and DATA (pass bytes in or out). The OS drives the device through a four-step protocol โ€” step through it:

while (STATUS == BUSY)          // 1. wait until ready (poll)
    ;
write data to DATA register    // 2. hand over the data
write command to COMMAND        //    ...and the command (starts it)
while (STATUS == BUSY)          // 3. wait until done (poll)
    ;
The canonical device protocol: the OS drives a device by reading and writing its three registers. Time flows downward.
OS(driver code)
Device(hardware)
1 โ€” Wait until the device is ready
2 โ€” Send the request
3 โ€” Wait for completion
step 1 / 7 ยท time flows downward

This busy-wait is POLLING: the OS keeps reading the status register until the device is free. Simple โ€” but it burns CPU doing nothing useful.

Two ideas fall out. Step 1 and step 3 are polling โ€” busy-looping on the status register, which wastes CPU on a slow device. And when the CPU moves the data in step 2 (word by word), thatโ€™s programmed I/O (PIO) โ€” fine for a few bytes, costly for a 4KB block. Both inefficiencies set up the next section:

The Crux: How To Avoid The Costs Of Polling

How can the OS check device status without frequent polling, lowering the CPU overhead of managing a device?

Check yourself: devices and the canonical protocol

1.Why are devices attached through a HIERARCHY of buses instead of one shared bus?

2.A canonical device exposes three registers. What is each for?

3.In the canonical protocol, what is 'polling'?

4.What is programmed I/O (PIO)?

5.In step 2 of the protocol, why does writing the COMMAND register matter?

6.What is the main inefficiency of the canonical protocol as written?

6 questions