Professional Documents
Culture Documents
Recall that a stored program or von Neumann computer comprises a CPU that is made up of an ALU and a
control unit, a primary memory unit, a collection of I/O devices, and a bus system that interconnects the other
components, as illustrated in Figure 6.
(a) (b)
Figure 6: (a) The von Neumann architecture; (b) abbreviated form (Source: (Nutt, 2003))
As can be seen from the figure, I/O devices are attached to the computer bus. Data transfer between the various
components of the computer is through the bus system.
It is the job of the OS device manager to control all the computer’s I/O devices. The device manager issues
commands to devices, catches interrupts, and handles errors. It also provides an interface between the devices
and the rest of the system that is simple and easy to use.
I/O devices can be categorised by the function they perform, viz.: input devices like the keyboard and mouse;
output devices like the printer and screen; storage devices like disks, which are both input and output devices;
and communication devices like network cards and serial and parallel ports, which also act as both input and
output devices.
I/O devices can also be classified by the type of data they handle, as block devices and character devices. A
block device stores or reads data in fixed-size blocks. A typical example is a disk. A character device on the
other hand delivers or receives a stream of characters without regard to any block structure. Printers, network
cards, mice, as well as most other devices that are not disk-like are character devices.
Most operating systems treat all I/O devices in the same general manner, but treat the processor and memory
differently. Device management refers to the way these I/O devices are handled.
Why is device management important? Computation (i.e., use of the processor) happens to be many, many
times faster than I/O. If there are several processes running on a computer therefore, and the processor has to
halt until I/O is completed for a given process, then the overall computation time for all the processes could be
very long. Even if through some mechanism, the processor could be made to attend to other processes that need
its attention, and only periodically check to see if I/O for a given process is complete so that that process could
also be allocated processor time, time is wasted whenever the processor checks to determine if I/O for that
process is still in progress2.
Secondly, apart from the great disparity in processor and I/O speeds, there is also great disparity in the speeds
of I/O devices. The keyboard and mouse for example, are millions of times slower than network cards; the
device manager must therefore be capable of managing these speed differences amongst I/O devices.
2 Busy-wait is the term used to describe what happens to the processor in such a circumstance, since the
processor is busy (testing to see if I/O is completed) but is effectively waiting for I/O to complete before the
processor can be allocated to the process that was involved in I/O.
We explain below, how in the hypothetical example above, the software interface between the controller and the
OS works.
We notice that the controller has a number of registers (3 in this example): command, status, and data registers.
The status register comprises a number of flag bits, including a busy bit, a done bit, and an error bit which
is set whenever the controller encounters an error it cannot recover from. The truth table shows how the busy
and done flags are used to place the controller in different states.
In the idle state (when both flags are set to 0), the software is allowed to place a command in the
controller’s command register, and data in its data register. The direction into which the data will travel
depends on the contents of the command register: if it is an input command, data will be read from the
device; if it is an output command, data will be written to the device.
The presence of the new command in the command register causes the busy flag to be set (resulting in
the 1, 0 or working state), and the data is moved into or out of the device, depending on the command.
The process knows which direction to move data by reading the state from the status register
At the end of the operation, the controller clears the busy flag and sets the done flag, i.e., the device is
set to the 0, 1 or finished state.
If the read or write operation happened without error, the done flag is cleared, and the device returns to
the 0, 0 or idle state to indicate that the device is again ready for use.
If the controller encountered an error, then the error flag in the status register will be set.
Memory-Mapped I/O
The second approach (used in all modern computer systems) to communicate with I/O devices uses memory-
mapped I/O. In the memory-mapped I/O approach, devices are mapped to primary memory addresses rather
than having specialized device addresses. In this approach, all the control registers and data buffers are mapped
into memory space by assigning a unique memory address to each control register and ensuring that such
addresses are not assigned in primary memory. Some computer systems use a hybrid approach in which data
buffers are mapped to memory but separate I/O ports are used for the control registers.
Advantages of memory-mapped input include the following:
1. No special I/O instructions (which are generally supported only through an assembly language routine
call, with the additional overheads involved) are required
2. The problem in the traditional approach of requiring new categories of I/O instructions, giving rise to a
large number of instruction set types (and larger programming possibilities and difficulties to the
programmer) is avoided. With the memory-mapped approach, every I/O instruction is treated the same
way equivalent memory instructions are treated.
3. The OS can better control which processes can use which I/O device
Figure 10. Comparing (a) conventional and (b) Use of DMA controller
(b)
(a)
Figure 11: (a) Steps in starting an I/O device and getting an interrupt. (b) Interrupt processing
(Adapted from Tanenbaum (2001))
Interrupts are an unpleasant fact of life, and their handlers should be hidden to the lowest level, with as little
involvement of the rest of the operating system as possible.
The next layer up are the device drivers. As we saw earlier, device drivers are specific to individual devices;
device drivers are device-specific code, typically written by the device manufacturer, for controlling the device.
Device drivers can control devices because they have access to the device controller registers.
The device-independent part of the operating system provides the following functions:
1. Uniform interfacing for device drivers
2. Buffering
3. Error reporting
4. Allocating and releasing dedicated devices
5. Providing a service-independent block size
Uniform interfacing for device drivers
The idea here is to make all I/O devices and drivers look more-or-less the same to the rest of the OS. Hence,
each driver simple plugs into the OS. And because the driver interface is the same, different driver writers can
independently write drivers for their devices knowing that they will work as expected. Without this facility,
each time a new device comes along, one would have to modify the OS to be able to handle it.
Buffering
Buffering is a technique widely used in I/O. Consider for example, a process that wants to read data from a
modem. A number of possibilities are illustrated in Figure 13.
We now look more closely at seek time, the most costly component of access time. Consider a
multiprogramming system for example, with multiple requests to access the disk at the same time. Assume for
example that requests are made for blocks on tracks 12, 123, 50, 13, 124, and 49 in that order. Suppose that the
time it takes to initiate the seek operation for a track is X ms, and that it requires YK additional ms to get to a
track Y tracks away from the current track. Assuming the value of K to be 3, the seek time for the problem
above (assuming the tracks are accessed in the same order) is:
CF
+ (X + 3*(123 – 12))
+ (X + 3*(123 – 50))
+ (X + 3*(50 – 13))
+ (X + 3*(124 – 13))
+ (X + 3*(124 – 49)) = 5X * 921 ms
where CF is the time it takes to access the first of the tracks (track 12 in this example), and varies depending on
the original position of the read/write head. Minimizing seek time could lead to a great reduction in the overall
access time. Various algorithms have been developed in this regard.