Skip to content

Epoll Trigger Mode

In Linux, epoll is a high-performance I/O event notification system that allows the application to monitor multiple file descriptors to determine if I/O operations can be performed on any of them.

There are two trigger modes: Level-Triggered (default) and Edge-Triggered.

Level-Triggered (LT)

In level-triggered mode (the default mode for epoll), the application is notified about an event as long as the condition persists (e.g. a fd remains ready for reading or writing). This means that if there is data available to read or buffer ready to write, epoll will continue to notify the application repeatedly until the condition changes, such as when all the data has been read or the buffer is full.

#include <sys/epoll.h>

struct epoll_event ev;
ev.events = EPOLLIN; // level-triggered (default), input events
ev.data.fd = fd;

epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);

This mode is easier to use because the application doesn't risk missing events, even if it doesn't process them immediately. However, it can lead to redundant notifications, which might reduce performance in scenarios involving frequent and high-volume events.

Edge-Triggered (ET)

In edge-triggered mode, epoll notifies the application about an event only when the state changes (e.g. from not-ready to ready). Once notified, the application must handle the event completely, such as reading all available data or writing all buffered data, because no further notifications will be sent for the same state.

#include <sys/epoll.h>

struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET; // edge-triggered, input events
ev.data.fd = fd;

epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);

When using non-blocking I/O, if the operation cannot proceed immediately (e.g. there is no more data to read or the output buffer is full), the system call will return EAGAIN. The application must continue processing in a loop until EAGAIN is encountered, ensuring that all data is handled. Failure to do so can result in unprocessed data being left unread or unwritten, with no further notifications, potentially causing the application to miss critical events.

// non-blocking mode
ssize_t n;
while ((n = read(fd, buffer, buffer_size)) > 0) {
    // process the data
}
if (n == -1 && errno != EAGAIN) {
    perror("read error")
}

Edge-Triggered mode is best used in high-performance applications that handle many file descriptors, such as servers or real-time systems, where reducing notification overhead and improving efficiency is crucial. It’s ideal when you need to minimize the number of system calls and notifications. However, ET requires careful event handling, ensuring that events are fully processed and non-blocking I/O is used, as further notifications won’t be sent unless the state changes.