Obviously, most data on which we compute resides outside of the computer itself; perhaps it’s originally
on paper receipts, or in lists on paper. And when computation is complete, we want to see the results outside of
the computer’s own memory; on a display, or on paper, for example.
While there is variation in the way CPUs, memory, and caches are implemented, there is even more variation
in the ways in which I/O is implemented. First of all, there are many different I/O devices. Some are for interacting
with humans, such as keyboards, mice, touch screens, and displays. Others are for use by the computer directly,
such as disk drives, tape drives, and network interfaces.
I/O devices also vary enormously in speed, and they’re all much slower than the CPU and main memory. A
typist working at 40 words per minute is going pretty fast, and striking about 200 keys a minute, or one key every
.3 seconds. Let’s compute how many instructions a 1 GHz personal computer might execute during that .3 seconds.
Some instructions execute on one clock cycle, but many require more than one. Let’s assume that an average
instruction requires 3 cycles. If that’s the case, then the 1 GHz computer executes 330 million instructions per
second, or 99 million instructions in the time it takes to type one letter.
To get a feel for the difference in speed between the keyboard and the CPU, imagine that the typist walks
one foot in the time it takes to type one letter, and imagine also that the computer travels one foot in the time it
takes to execute an instruction. If that were the case, then in the time the typist walks a foot, the computer travels
18,750 miles, or about three quarters of the way around the earth!
In the early days of computing, the CPU would wait for each character to be typed. A machine instruction
would ready the keyboard interface to accept a character from the keyboard, and the next instruction would test
to see if the character had been received. If the character had not yet been received, the program would simply
loop, testing (“polling”) to see if the character had been received. This is called “programmed I/O with polling,”
or “busy waiting.” It’s a simple but prohibitively costly approach.
Today computers use an “interrupt system” to avoid busy waiting, and the operating system supervises
all I/O. Each I/O device is connected to the computer via an “I/O controller.” An I/O controller is a small,
special-purpose computer within the computer. It has a few well-defined functions, and a small amount of
memory of its own with which to “buffer” (store temporarily) the information being sent or received.
When a program requires output, for example, the operating system moves the data to the buffer memory of
the I/O controller for the device, and commands the I/O controller to start the operation. From that point on, the
main computer is free to do other work, while the I/O controller handles the details and timing of moving the data
to its destination. When the data transfer is complete, the I/O controller creates an “interrupt” which notifies the
main computer that the transfer is now finished. The operating system responds to the interrupt in an appropriate
way, perhaps by starting another output operation to the same device (think of multiple lines going to a printer).
When a program requires input, the operating system will suspend the execution of the requesting program
and command the I/O controller of the device to start reading the necessary data. The operating system will then
transfer control of the CPU to a different program, which will execute while the first program is waiting for its
input. When the requested data become available, the I/O controller for the device will generate an interrupt.
The operating system will respond by suspending the execution of the second program, moving the data from
the buffer on the I/O controller to the program that requested the data initially, and restarting the first program.
The interrupt system is used for all data transfers today. While that is so, there are also some useful
categorizations of device types. Devices may be categorized as character devices or block devices. A keyboard
is a character device, and a disk is a block device. A character device transfers a character (8 bits) at a time, and
a block device transfers a buffer, or set of data, at a time.
Other examples of character devices include telephone modems and simple terminals. Other examples of
block devices include CD-ROM drives, magnetic tape drives, network interfaces, sound interfaces, and blocks
of memory supporting devices like displays. Character devices interrupt on each character (8 bits) transferred,
and block devices interrupt only when the entire block has been transferred.
Modern computer designs usually include a facility called direct memory access (DMA) for use with block
devices. The DMA controller is its own special computer with access to memory, and it shares access to main
memory with the CPU. DMA moves data directly between the buffer in the I/O controller and main memory,
and it does so without requiring any service from the CPU.
Block devices can be used without DMA and, when they are used that way, the practice is called
“programmed I/O with interrupts.” With programmed I/O, the block device interrupts when the buffer is ready,
but the operating system must still use the CPU to move the data between the buffer on the I/O controller and
the destination in main memory.
When DMA is used with a block device, the data are transferred directly between the device and main
memory, without requiring assistance from the operating system and the CPU. The operating system starts the
transfer by specifying an address at which to start and the count of bytes to transfer. The CPU is then free to
continue computing while the data are moved in or out. This is a further improvement in system efficiency, and
today DMA is almost universally used for disk and other block transfers.
No comments:
Post a Comment