ptg10805159
500 Advanced I/O Chapter 14
14.4 I/O Multiplexing
When we read from one descriptor and write to another, we can use blocking I/O in a
loop, such as
while ((n = read(STDIN_FILENO, buf, BUFSIZ)) > 0)
if (write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");
We see this form of blocking I/O over and over again. What if we have to read from
two descriptors? In this case, we can’t do a blockingreadon either descriptor, as data
may appear on one descriptor while we’reblocked in areadon the other.Adifferent
technique is required to handle this case.
Let’s look at the structureofthetelnet( 1 )command. In this program, we read
from the terminal (standardinput) and write to a network connection, and we read
from the network connection and write to the terminal (standardoutput). At the other
end of the network connection, thetelnetd daemon reads what we typed and
presents it to a shell as if we werelogged in to the remote machine. Thetelnetd
daemon sends any output generated by the commands we type back to us through the
telnetcommand, to be displayed on our terminal. Figure14.13 shows a pictureof
this arrangement.
user at a
terminal
telnet
command
telnetd
daemon
Figure 14.13Overview oftelnetprogram
Thetelnetprocess has two inputs and two outputs.We can’t do a blockingread
on either of the inputs, as we never know which input will have data for us.
One way to handle this particular problem is to divide the process in two pieces
(using fork), with each half handling one direction of data. We show this in
Figure14.14. (Thecu( 1 )command provided with System V’suucpcommunication
package was structured like this.)
user at a
terminal
telnetd
daemon
telnetcommand
(parent)
telnetcommand
(child)
Figure 14.14Thetelnetprogram using two processes
If we use two processes, we can let each process do a blockingread.But this leads to a
problem when the operation terminates. If an end of file is received by the child (the