7.3. Blocking and Nonblocking I/OΒΆ

Some control over how the wait for I/O to complete is accommodated is available to the programmer of user applications. Most I/O requests are considered blocking requests, meaning that control does not return to the application until the I/O is complete. The delayed from systems calls such read() and write() can be quite long. Using systems calls that block is sometimes called synchronous programming. In most cases, the wait is not really a problem because the program can not do anything else until the I/O is finished. However, in cases such as network programming with multiple clients or with graphical user interface programming, the program may wish to perform other activity as it continues to wait for more data or input from users.

One solution for these situations is to use multiple threads so that one part of the program is not waiting for unrelated I/O to complete. Another alternative is to use asynchronous programming techniques with nonblocking system calls. An asynchronous call returns immediately, without waiting for the I/O to complete. The completion of the I/O is later communicated to the application either through the setting of some variable in the application or through the triggering of a signal or call-back routine that is executed outside the linear control flow of the application.

../_images/sync_async.png

Blocking I/O system calls (a) do not return until the I/O is complete. Nonblocking I/O system calls return immediately. The process is later notified when the I/O is complete.

A good example of nonblocking behavior is the select() system call for network sockets. Using select(), an application can monitor several resources at the same time and can also poll for network activity without blocking. The select() system call identifies if data is pending or not, then read() or write() may be used knowing that they will complete immediately.

Note

Correct asynchronous programming can be complex, but since asynchronous programs have only one thread of execution, problems of Deadlock and Data Inconsistency are eliminated. For this reason, several programming frameworks exist that handle the difficult I/O issues making asynchronous programming much easier.

Asynchronous programming with call backs appears to be the most common approach for graphical user interface programming. It also has some advocates in the network programming realm, but multi-threaded programming is more often used with network programming.