Input/output (I/O)
Required reading: Chapter 15, 16, and 17
Overview
- Programs perform input/output through devices that interact with
the real world. An electronic device controler typically controls the
device. The controler is connected through a bus to the rest of the
computer (processor and memory). By programming the controler, a
program on the processor can control the device. Typically the
software to control the device is divided in two pieces: the
device-independent software and the device-dependent software, the
driver.
Interface issues:
- Devices in general fall in two categories: block devices (e.g.,
disk) and character devices (e.g., terminal, printer). Block devices
break bytes up into block. Character devices represent a continuous
stream of bytes.
- Names for devices allow users to interact with devices (e.g.,
mount /dev/rk0/ /mnt). For example, /dev/rk0 specifies the i-node for
a special file. the i-node contains a major device number and a minor
number. The major device number indexes into bdevsw (block device) or
cdevsw (character device). The minor number indexes into an array
within that device driver (if there are multiple devices of the same
type).
- The driver can access the driver either has through special memory
locations (memory-mapped I/O) or with reserved instructions. Most
common today is memory-mapped I/O.
- The device works in parallel with the main processor. Therefore,
the processor and controler need a way to coordinate. The two main
styles for coordination are polling and interrupts.
- Many computers support DMA (direct-memory access) for larger data
transfers between device and memory. This allows a device to transfer
data from device to memory (and vice versa) without the CPU's
involvement. DMA reduces the load on the CPU and makes better use of
the bus.
Writing software for device drivers is challenging:
- devices are designed by hardware designers
- concurrency within driver (e.g., interrupt handler). typically
addressed by disabling and enabling interrupts carefully.
- concurrency between driver and device. typically addressed by
ensuring that each register has only one writer.
- potential for deadlock
- address translation
- Buffer Cache. Disk I/O is slow compared to CPU. The fastest I/O
is the one you don't do; thus, cache data blocks in main memory. Buffer
cache design issues:
- Division of memory between programs and buffer cache.
- Replacement policy. LRU, MRU, etc.
- Write behind or not? Benefit: delays writes, which may provide
write absorption (multiple writes to same block result in one I/O
operations). Write behind, unfortunately, opens the window for system
failures. Write behind also introduces additional concurrency (e.g., a
read request may have to wait until a dirty buffer has been written
out).
- Asynchronous operations. Can caller of operations on the buffer
cache proceed while the buffer cache is performing the requested
operation?
V6 code examples