Skip to content

epoll Internals

Purpose

epoll is designed to efficiently monitor a large number of file descriptors.

Unlike poll(), which scans every registered file descriptor on each call, epoll maintains internal data structures so that userspace only receives file descriptors that are currently ready.

Core Components

An epoll instance primarily consists of two internal lists:

Interest List
    All monitored file descriptors.

Ready List
    File descriptors that are currently ready and should be returned to userspace.

Each monitored file descriptor is represented internally by an epitem.

Typical Flow

epoll_ctl(ADD)



Interest List



driver .poll()



Ready List



epoll_wait()



Userspace

Driver Responsibility

Device drivers never implement epoll-specific callbacks.

The driver only provides the standard .poll() callback.

static __poll_t mydev_poll(struct file *file,
                           poll_table *wait)
{
    poll_wait(file, &dev->wq, wait);

    if (data_available(dev))
        return POLLIN;

    return 0;
}

The same callback is shared by:

  • poll()
  • select()
  • epoll()

Interest List

The Interest List stores all monitored file descriptors together with:

  • interested events
  • driver poll callback
  • driver private data

Entries remain in the Interest List until removed by epoll_ctl(DEL).

Ready List

The Ready List stores file descriptors that should be returned by the current epoll_wait().

It is not the source of truth.

The actual readiness always comes from the driver's current state.

After returning events to userspace, entries are removed from the Ready List.

If the device is still ready, the next driver .poll() call places the entry back into the Ready List.

Level Trigger (LT)

Level Trigger repeatedly reports readiness while the device remains ready.

Device ready


epoll_wait()


POLLIN


Device still ready


epoll_wait()


POLLIN

Applications should continue reading until the device is no longer ready.

Edge Trigger (ET)

Edge Trigger reports only readiness transitions.

Not Ready


Ready


Notify once


Still Ready


No notification


Not Ready


Ready


Notify again

Applications typically read until EAGAIN to avoid missing future notifications.

poll vs epoll

poll epoll
Scans all file descriptors Monitors registered file descriptors
O(N) scan each call Scales well for many file descriptors
Userspace rebuilds pollfd[] every call Kernel maintains Interest List
Suitable for a small number of descriptors Suitable for large event-driven systems

Common Misconceptions

Ready List stores device state

No.

The Ready List is only a temporary notification queue.

The driver state remains the source of truth.

Drivers need epoll support

No.

Drivers only implement the standard .poll() callback.

The epoll subsystem manages all epoll-specific behavior.

  • Blocking and Non-blocking I/O
  • Wait Queue and poll Support
  • fasync and SIGIO