1328 Chapter 63
Which technique?
During the course of this chapter, we’ll consider the reasons we may choose one of
these techniques rather than another. In the meantime, we summarize a few points:
z The select() and poll() system calls are long-standing interfaces that have been
present on UNIX systems for many years. Compared to the other techniques,
their primary advantage is portability. Their main disadvantage is that they
don’t scale well when monitoring large numbers (hundreds or thousands) of
file descriptors.
z The key advantage of the epoll API is that it allows an application to efficiently
monitor large numbers of file descriptors. Its primary disadvantage is that it is
a Linux-specific API.
Some other UNIX implementations provide (nonstandard) mechanisms simi-
lar to epoll. For example, Solaris provides the special /dev/poll file (described
in the Solaris poll(7d) manual page), and some of the BSDs provide the kqueue
API (which provides a more general-purpose monitoring facility than epoll).
[Stevens et al., 2004] briefly describes these two mechanisms; a longer discus-
sion of kqueue can be found in [Lemon, 2001].
z Like epoll, signal-driven I/O allows an application to efficiently monitor large
numbers of file descriptors. However, epoll provides a number of advantages
over signal-driven I/O:
- We avoid the complexities of dealing with signals.
- We can specify the kind of monitoring that we want to perform (e.g., ready
for reading or ready for writing). - We can select either level-triggered or edge-triggered notification (described
in Section 63.1.1).
Furthermore, taking full advantage of signal-driven I/O requires the use of
nonportable, Linux-specific features, and if we do this, signal-driven I/O is no
more portable than epoll.
Because, on the one hand, select() and poll() are more portable, while signal-driven
I/O and epoll deliver better performance, for some applications, it can be worth-
while writing an abstract software layer for monitoring file descriptor events. With
such a layer, portable programs can employ epoll (or a similar API) on systems that
provide it, and fall back to the use of select() or poll() on other systems.
The libevent library is a software layer that provides an abstraction for monitor-
ing file descriptor events. It has been ported to a number of UNIX systems. As
its underlying mechanism, libevent can (transparently) employ any of the tech-
niques described in this chapter: select(), poll(), signal-driven I/O, or epoll, as
well as the Solaris specific /dev/poll interface or the BSD kqueue interface. (Thus,
libevent also serves as an example of how to use each of these techniques.) Written
by Niels Provos, libevent is available at http://monkey.org/~provos/libevent/.