Blocking v. Nonblocking I/O
From the programmer’s point of view, I/O system calls exhibit one of three kinds of behaviour:
1. Blocking: process suspended until I/O completed
• easy to use and understand.
• insufficient for some needs.
2. Nonblocking: I/O call returns as much as available
• returns almost immediately with count of bytes read or written (possibly 0).
• can be used by e.g. user interface code.
• essentially application-level “polled I/O”.
3. Asynchronous: process continues to run while I/O executes
• I/O subsystem explicitly signals process when its I/O request has completed.
• most flexible (and potentially efficient).
• . . . but also most difficult to use.
Most systems provide both blocking and non-blocking I/O interfaces; modern s systems(e.g. NT, Linux) also support asynchronous I/O, but used Infrequently.
Other I/O Issues
• Caching: fast memory holding copy of data
– can work with both reads and writes
– key to I/O performance
– e.g. ordering I/O requests via per-device queue
– some operating systems try fairness. . .
• Spooling: queue output for a device
– useful for “single user” devices which can serve only one request at a time (e.g. printer)
• Device reservation:
– system calls for acquiring or releasing exclusive access to a device (careful!).
• Error handling:
– e.g. recover from disk read, device unavailable, transient write failures, etc.
– most I/O system calls return an error number or code when an I/O request fails.
– system error logs hold problem reports.