Alternative I/O Models 1329
63.1.1 Level-Triggered and Edge-Triggered Notification
Before discussing the various alternative I/O mechanisms in detail, we need to dis-
tinguish two models of readiness notification for a file descriptor:
z Level-triggered notification: A file descriptor is considered to be ready if it is
possible to perform an I/O system call without blocking.
z Edge-triggered notification: Notification is provided if there is I/O activity (e.g.,
new input) on a file descriptor since it was last monitored.
Table 63-1 summarizes the notification models employed by I/O multiplexing,
signal-driven I/O, and epoll. The epoll API differs from the other two I/O models in
that it can employ both level-triggered notification (the default) and edge-triggered
notification.
Details of the differences between these two notification models will become
clearer during the course of the chapter. For now, we describe how the choice of
notification model affects the way we design a program.
When we employ level-triggered notification, we can check the readiness of a
file descriptor at any time. This means that when we determine that a file descriptor
is ready (e.g., it has input available), we can perform some I/O on the descriptor, and
then repeat the monitoring operation to check if the descriptor is still ready (e.g., it
still has more input available), in which case we can perform more I/O, and so on. In
other words, because the level-triggered model allows us to repeat the I/O moni-
toring operation at any time, it is not necessary to perform as much I/O as possible
(e.g., read as many bytes as possible) on the file descriptor (or even perform any I/O
at all) each time we are notified that a file descriptor is ready.
By contrast, when we employ edge-triggered notification, we receive notifica-
tion only when an I/O event occurs. We don’t receive any further notification until
another I/O event occurs. Furthermore, when an I/O event is notified for a file
descriptor, we usually don’t know how much I/O is possible (e.g., how many bytes
are available for reading). Therefore, programs that employ edge-triggered notifi-
cation are usually designed according to the following rules:
z After notification of an I/O event, the program should—at some point—perform
as much I/O as possible (e.g., read as many bytes as possible) on the corre-
sponding file descriptor. If the program fails to do this, then it might miss the
opportunity to perform some I/O, because it would not be aware of the need
to operate on the file descriptor until another I/O event occurred. This could
lead to spurious data loss or blockages in a program. We said “at some point,”
because sometimes it may not be desirable to perform all of the I/O immediately
after we determine that the file descriptor is ready. The problem is that we may
Table 63-1: Use of level-triggered and edge-triggered notification models
I/O model Level-triggered? Edge-triggered?
select(), poll() •
Signal-driven I/O •
epoll ••