IO

From COMP15212 Wiki
Revision as of 13:32, 6 May 2024 by gravatar U05730dg [userPHRhYmxlIGNsYXNzPSJ0d3BvcHVwIj48dHI+PHRkIGNsYXNzPSJ0d3BvcHVwLWVudHJ5dGl0bGUiPkdyb3Vwczo8L3RkPjx0ZD51c2VyPGJyIC8+PC90ZD48L3RyPjwvdGFibGU+] (talk | contribs) (→‎Block and Character devices)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Depends on Resources

A computer which cannot communicate with the outside world is of no value. Communication may be through a plethora of peripheral devices, all hardware devices, all different. It is therefore the task of an operating system to intermediate between these devices and the applications code and provide a sensible abstraction and virtualisation of the I/O resources.

In general, although devices may be diverse in nature, it is useful to be able to treat them in similar ways, if possible. For example, many devices – keyboards, audio output, video displays, networks – can be interfaced to via a serial stream of bytes; a stream can also be recorded in a file for future use.

One way of thinking of a file is that it is a way of communicating through time (to the same or a different application on the same computer) which is similar to communicating through space to an application on a different machine, person or thing.

It is also worth noting that the I/O devices themselves may be virtual. The clearest contemporary example is USB where a single physical interface is shared by many physical devices.

Block and Character devices

A useful – if not universal – classification of I/O devices is into those which handle data as well-defined, fixed size blocks and those which use indefinite length streams.

  • Block devices include: magnetic disks, USB sticks, DVDs.
    The data blocks have an associated address – although this is not an address in the same sense as a memory address.
  • Character devices include: keyboard, screen, printer, network.
    Characters just ‘stream’ along; they are not independently addressable.

It is sometimes useful to have different interfaces to the same device: thus it may be possible to stream characters onto a disk, although this is done by buffering and (de)serialising one form into the other. (There is an interactive demonstration in this article.)

Abstraction

The O.S. has a particular place in the I/O abstraction. It manages the hardware devices via its dedicated device drivers and – as far as possible – makes I/O devices look the same. It is this characteristic which allows a USB stick to appear amongst the disks in the filestore or for the screen output to be redirected to the printer.

It is not (really) the O.S. job to make sense of the data. Thus (for example) if the printer understands only PostScript it is the application’s job to encode the data appropriately. The O.S. tasks are to ensure that the data reaches the appropriate resource without interfering with other applications.

I/O stack

Although they may not always be distinct, Tanenbaum & Bos identify four levels in the software I/O ‘stack’:

  • User-level processing: an example would be the formatting done by library calls such as printf().
    This layer may also provide buffering and spooling.
  • Device-independent system calls: the important level in abstraction, this layer makes diverse devices obey similar interface conventions. It therefore allows the interfacing of many devices – including newly introduced hardware – to any application.
    Similarly, it provides a standard interface for new drivers in the next layer of software.
    The device-independent layer may provide buffering, such as the accumulation of characters into blocks, where this is appropriate for the device.
  • The device driver translates the standardised commands into the specific values and sequences needed to operate the hardware. One device driver will only support a small class of devices (perhaps only one device). It will probably communicate with the hardware directly – particularly for initialisation – although in operation it may spend much of its time blocked waiting for the hardware which is serviced by the software layer below.
  • Interrupt handlers provide the moment-to-moment servicing for the device. Ideally, interrupt service routines should be short – they may be stopping something else running – and pass control back to the driver process.
    Different mechanisms may be employed in this communication: signals, freeing a mutex, message passing etc. but all are basically allowing another process/thread to proceed (usually) in the kernel.
    In real-time systems interrupt latency can be particularly important. These may allow interrupt service routines to pre-empt other interrupt service routines (which are less urgent and therefore lower priority). They can often free-up high priority processes too, thus causing context switching and returning to a different process.

Access mechanisms

Typical I/O jobs involve the transfer of data (blocks or streams) into or out of a designated area of memory. The memory may be a buffer within the O.S. itself (acting as a queue, for example) or somewhere directly visible in an application’s address space. Whatever is required there needs to be a transfer between the peripheral device and the RAM. There are alternative ways to do this and the appropriate choice depends on the facilities available and the required transfer bandwidth.

It should be noted that the memory is typically assumed to be available all the time (virtual memory will be ignored for the moment) whereas the input/output availability is not always guaranteed (disk may need to turn first; robot may need to move; etc.)

  • Processor polling. The processor checks the peripheral device directly and loops in a busy-wait cycle until each transfer is ready.
    This is a simple mechanism but it is generally deprecated because it can waste a lot of valuable processor time doing nothing useful. It can be quite flexible if it is known that the incoming/outgoing data will not cause long waits though.
  • Interrupt driven I/O. The processor sets up an interrupt service then runs some other task. Interrupts will cause a partial context switch when a transfer is ready and the processor can perform the transfer and then resume the interrupted task.
    A typical application might be dealing with keyboard input: the processor is interrupted by a key press and reads and transfers the key code into a FIFO buffer from where it can later be read by a system call.
    Interrupt-driven I/O is probably the commonest form of I/O interface and is suitable for many low- to medium-bandwidth applications. It can be used on a character-by-character basis or – if the peripheral contains a larger buffer – can have reduced overhead by interrupting on a block-transfer basis.
    Interrupt overheads can still have a significant impact on processor time, though. There is also an issue of the response time or “interrupt latency” in that it takes some time for the processor to respond to the request. This limits the transfer rate and can be particularly important in real-time systems.

IO by interrupt

  • DMA transfers. With some extra hardware the transfer can be performed without processor intervention – by Direct Memory Access. This first requires a DMA controller to be set up with the relevant information, such as the memory area to use. Then, when the peripheral is ready to transfer, it uses the DMA controller (instead of interrupting the processor) to perform the transfer.
    There is clearly an additional hardware cost here – and the mechanism is more complex than interrupting. On the other hand there is (almost) no disturbance to the processor during the transfer so processing is maximised whilst interrupt latency is typically low.
    DMA is particularly useful for high-bandwidth transfers such as from/to disks or networks. It can also provide energy-efficiency benefits if there is a lot of I/O, since a dedicated DMA controller moves data more efficiently that a general-purpose processor.

IO by DMA


Also refer to: Operating System Concepts, 10th Edition: Chapter 12, pages 489-525


Articles on IO
Cacheability • Device Drivers • Direct Memory Access (DMA) • IO • Interprocess Communication • Interrupt Controller • Interrupt Service Routines (ISRs) • Interrupts • Libraries • Peripheral devices • Pipes • Queues • Queues Extra • Resources • Shell • Sockets • Spooling and Buffering • Starvation • Streams • System Calls • Thrashing • Timers • Using Peripherals • Virtualisation • Write Buffer