andersch.dev

<2025-04-19 Sat>
[ linux os ]

epoll

epoll is a Linux system call that enables scalable I/O multiplexing. It allows for concurrency by monitoring multiple file descriptors to see which ones are ready for I/O operations. The POSIX predecessors for this call are select and poll, but while these have O(n) performance, epoll is O(1).

Example

A toy example that monitors stdin. A more useful program would e.g. monitor network sockets.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <fcntl.h>

#define MAX_EVENTS 10

int main() {
    struct epoll_event ev, events[MAX_EVENTS];

    int epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) { /* error handling */ }

    int server_fd = STDIN_FILENO; // stdin as file descriptor to monitor

    // make stdin non-blocking
    fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL, 0) | O_NONBLOCK);

    ev.events = EPOLLIN; // Monitor for input events
    ev.data.fd = server_fd;

    // add file descriptor to epoll instance
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) == -1) {
        perror("epoll_ctl: server_fd");
        exit(EXIT_FAILURE);
    }

    printf("Monitoring stdin for input. Type something and press enter.\n");

    /* event loop */
    while (1) {
        int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); // -1 == wait indefinitely
        if (nfds == -1) { /* error handling */ }

        // Process events
        for (int i = 0; i < nfds; i++) {
            if (events[i].data.fd == server_fd) {
                char buffer[256];
                int len = read(server_fd, buffer, sizeof(buffer) - 1);
                if (len > 0) {
                    buffer[len] = '\0';
                    printf("Received: %s", buffer);

                    // exit if user types "quit"
                    if (strncmp(buffer, "quit", 4) == 0) {
                        printf("Exiting...\n");
                        close(epoll_fd);
                        exit(EXIT_SUCCESS);
                    }
                }
            }
        }
    }

    close(epoll_fd);
    return 0;
}

Resources