(read chapter 13 of the dinosaur book)
The two main jobs of a computer are I/O and processing.
Controlling all the various devices connected to the computer is a major problem for the operating system. There are various devices, with different interfaces, and various characteristics, and the operating system somehow needs to figure out how to control each one, despite all the differences.
In order to easier use all the different devices, the operating system uses device drivers, which is code that manipulates some hardware via some defined interface.
Hardware can be connected to the computer via various approaches. Via a daisy chain, a bus, a port, an expansion bus, etc.
Usually, there is some controller that sits in between the computer and the actual hardware. The controller controls (and assists) in I/O interaction between the computer and the hardware.
The controller also assists in memory mapped I/O.
(more long and weirdo explanation in class).
When communicating with the controller (hardware), we can poll for changes. Polling requires CPU cycles.
If polling becomes too expensive, we can use interrupts to drive the communication process. We initialize the communication via an interrupt, which hands over control to the controller, which in turn notifies the application (and CPU) of the I/O status (completion, etc.) via an interrupt.
Interrupts have various priorities, so that some interrupts are handles first, etc.
Software interrupts are called traps, and usually have less priority than hardware interrupts.
Direct Memory Access
We can allow the hardware to do I/O from/to our memory via a technique called Direct Memory Access. We setup some memory with appropriate data structures, etc., and then tell the controller where it is in memory. The controller can then read the memory independently of the CPU. It might steal some memory cycles, but overall, the system will seem to run faster (since CPU will be utilized more). The cycles also don't effect the various caches that the CPU has, so generally the performance from memory mapped IO is fairly good.
Application I/O Interface
Applications have different I/O interfaces, but generally those are broken up onto several general classes.
Block devices operate on blocks. Like hard drives, etc. We can read a block, and write a block. These usually provide access such as read/write.
Character stream devices. These provide access to get() and put() methods, which allow us to write/write a character at a time.
There are other varieties which we can introduce, which include sequential vs. random access, synchronous and asynchronous, sharable or dedicated, speed of operation, read/write mode, etc.
Clocks and Timers
Clocks and timers generally provide interrupt functionality. We can setup an interrupt to happen in some specified amount of time, or even make it recurring. These timers are usually not very precise in terms of time keeping, and for actual 'clock' a different device is used to keep time.
The operating system must deal with various I/O scheduling issues. The order in which I/O requests arrive are usually not the best order to execute them.
Many I/O devices utilize buffering to speed up transfers from one device to the next. Instead of writing/reading from device to device or from device to application, it's usually best to write data to some buffer, and then let the OS determine how best to utilize it.
In addition to buffering, the system can utilize caching.
Spooling is another form of buffering, which just means that when the device is slow and is not capable of handling too many requests at once, the spooling service still accepts requests and performs them at a later time. For example, a print spooler, which allows you to print 2 documents at the same time, yet, they'll actually be printed one at a time.
The operating system must also take care to detect various errors. If the operating system uses protected access to memory, it can usually limit the amount of damage a faulty device can do.
Kernel Data Structures
The kernel must maintain some data structures about the devices which are attached to the computer, and other relevant information. This is similar to keeping a list of open files, discussed in previous notes.
Transforming I/O to Hardware Operation
Transforming an application request into hardware is the job of the operating system. The operating system can use various tables, device drivers, controllers, etc., to make some simple request happen.
For example, to read a keyboard key, the operating system must initialize a keyboard controller, which when the key is typed, notifies the OS that the key is there (via an interrupt), at which point the operating system must go and pick up that key from the controller. It then translates the key scan code into the character you see appearing on the monitor. And this is done for every key you type! The process for reading/writing hard drives is quite a bit more complex.