1354 Chapter 63
sigtimedwait() (Section 22.10). These system calls return a siginfo_t structure that con-
tains the same information as is passed to a signal handler established with SA_SIGINFO.
Accepting signals in this manner returns us to a synchronous model of event process-
ing, but with the advantage that we are much more efficiently notified about the file
descriptors on which I/O events have occurred than if we use select() or poll().
Handling signal-queue overflow
We saw in Section 22.8 that there is a limit on the number of realtime signals that
may be queued. If this limit is reached, the kernel reverts to delivering the default
SIGIO signal for “I/O possible” notifications. This informs the process that a signal-
queue overflow occurred. When this happens, we lose information about which file
descriptors have I/O events, because SIGIO is not queued. (Furthermore, the SIGIO
handler doesn’t receive a siginfo_t argument, which means that the signal handler
can’t determine the file descriptor that generated the signal.)
We can reduce the likelihood of signal-queue overflows by increasing the limit
on the number of realtime signals that can be queued, as described in Section 22.8.
However, this doesn’t eliminate the need to handle the possibility of an overflow. A
properly designed application using F_SETSIG to establish a realtime signal as the “I/O
possible” notification mechanism must also establish a handler for SIGIO. If SIGIO is
delivered, then the application can drain the queue of realtime signals using
sigwaitinfo() and temporarily revert to the use of select() or poll() to obtain a com-
plete list of file descriptors with outstanding I/O events.
Using signal-driven I/O with multithreaded applications
Starting with kernel 2.6.32, Linux provides two new, nonstandard fcntl() operations
that can be used to set the target for “I/O possible” signals: F_SETOWN_EX and F_GETOWN_EX.
The F_SETOWN_EX operation is like F_SETOWN, but as well as allowing the target to be
specified as a process or process group, it also permits a thread to be specified as
the target for “I/O possible” signals. For this operation, the third argument of
fcntl() is a pointer to a structure of the following form:
struct f_owner_ex {
int type;
pid_t pid;
};
The type field defines the meaning of the pid field, and has one of the following values:
F_OWNER_PGRP
The pid field specifies the ID of a process group that is to be the target of
“I/O possible” signals. Unlike with F_SETOWN, a process group ID is specified
as a positive value.
F_OWNER_PID
The pid field specifies the ID of a process that is to be the target of “I/O
possible” signals.