Asynchronous sockets
allow a user program to receive an SIGIO signal when the state of
the socket changes. This state change can occur, for example, when
new data arrives. Currently the user would have to issue a select
system call in order to determine if data were available. If other
processing is required of the user program, the need to call select
can complicate an application by forcing the user to implement some
form of polling, whereby all sockets are checked periodically. Asynchronous
sockets allow the user to separate socket processing from other
processing, eliminating polling altogether. select
may still be required to determine exactly why the signal is being
delivered, or to which socket the signal applies.
Generation of the SIGIO
signal is protocol dependent. It mimics the semantics of select
in the sense that the signal is generated whenever select
returns true. It is generally accepted that connectionless protocols
deliver the signal whenever a new packet arrives. For connection
oriented protocols, the signal is also delivered when connections
are established or broken, as well as when additional outgoing buffer
space becomes available. Be warned that these assertions are guidelines
only; any signal handler should be robust enough to handle signals
in unexpected situations.
The delivery of the SIGIO signal is dependent upon two things.
First, the socket state must be set as asynchronous; this is done
using the FIOASYNC flag of the ioctl
system call. Second, the process group (pgrp) associated with the
socket must be set; this is done using the SIOCSPGRP flag of ioctl.
The sign value of the pgrp can lead to various signals being delivered.
Specifically, if the pgrp is positive, this implies that a signal
should be delivered to the process whose PID is the absolute value
of the pgrp. If the pgrp is negative, a signal should be delivered
to the process group identified by the absolute value of the pgrp.
Any application that chooses to use asynchronous sockets must
explicitly activate the described mechanism. The SIGIO signal is
a "safe" signal in the sense that if a process
is unprepared to handle it, the default action is to ignore it.
Thus any existing applications are immune to spurious signal delivery.
Notification that out-of-band data has been received is also
done asynchronously; see the section "Sending and Receiving
Out-of-band Data" in this chapter for more details.
The following example sets up an asynchronous SOCK_STREAM
listen socket.
This is typical of an application that needs to be notified when
connection requests arrive.
int ls; /* SOCK_STREAM listen socket initialized */ int flag = 1; /* for ioctl, to turn on async */ int iohndlr(); /* the function which handles the SIGIO */ signal (SIGIO, iohndlr); /* set up the handler */ if (ioctl (ls, FIOASYNC, &flag) == -1) { perror ("can't set async on socket"); exit(1); } flag = -getpid();/* process group negative = deliver to process */ if (ioctl (ls, SIOCSPGRP, &flag) == -1) { perror ("can't set pgrp"); exit(1); } /* signal can come any time now */
|
The following example illustrates the use of process group
notification. Note that the real utility of this feature is to allow
multiple processes to receive the signal, which is not illustrated
here. For example, the socket could be of type SOCK_DGRAM; a signal
here can be interpreted as the arrival of a service-request packet.
Multiple identical servers could be set up, and the first available
one could receive and process the packet.
int flag = 1; /* ioctl to turn on async */ int iohndlr(); signal (SIGIO, iohndlr); setpgrp(); /* set my processes' process group */ if (ioctl (s, FIOASYNC, &flag) == -1) { perror ("can't set async on socket"); exit(1); } flag = getpid(); /* process group + = deliver to each process in group */ if (ioctl (s, SIOCSPGRP, &flag) == -1) { perror ("can't set pgrp"); exit(1); } /* signal can come any time now */ |