epoll(7) Miscellaneous Information Manual epoll(7) epoll - - #include epoll poll(2) : , - . epoll edge-triggered, level-triggered . epoll epoll -- , : o interest ( epoll): , . o The ready list: the set of file descriptors that are "ready" for I/O. The ready list is a subset of (or, more precisely, a set of references to) the file descriptors in the interest list. The ready list is dynamically populated by the kernel as a result of I/O activity on those file descriptors. epoll : o epoll_create(2) epoll , ( epoll_create1(2) epoll_create(2)). o epoll_ctl(2) , interest epoll. o epoll_wait(2) -, , ( epoll). level-triggered edge-triggered epoll: edge-triggered (ET) level-triggered (LT). . , : (1) , (rfd), epoll. (2) 2 . (3) epoll_wait(2) rfd . (4) 1 rfd. (5) epoll_wait(2) . rfd epoll EPOLLET (edge-triggered), epoll_wait(2) 5, , , ; . , edge-triggered . 5 , . rfd - , 2, 3. 4, , epoll_wait(2) 5 . , EPOLLET, , , , - . epoll Edge Triggered (EPOLLET): (1) ; (2) , read(2) write(2) EAGAIN. , level-triggered ( , EPOLLET) epoll poll(2), , , . edge-triggered epoll , EPOLLONESHOT, epoll epoll_wait(2). EPOLLONESHOT, epoll_ctl(2) EPOLL_CTL_MOD. If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting on the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, just one of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios. autosleep autosleep /sys/power/autosleep , , , . , epoll_ctl(2) EPOLLWAKEUP. EPOLLWAKEUP events struct epoll_event; , epoll_wait(2), , epoll_wait(2). , wake_lock epoll_wait(2). /proc epoll , : /proc/sys/fs/epoll/max_user_watches ( Linux 2.6.28) , epoll . . , , 90 32- , , , 160 64- . , max_user_watches 1/25 (4%) (low memory), . epoll level-triggered poll(2), edge-triggered . , , listen(2). do_use_fd() , EAGAIN read(2) write(2). EAGAIN , do_use_fd() read(2) write(2) . #define MAX_EVENTS 10 struct epoll_event ev, events[MAX_EVENTS]; int listen_sock, conn_sock, nfds, epollfd; /* Code to set up listening socket, 'listen_sock', (socket(), bind(), listen()) omitted. */ epollfd = epoll_create1(0); if (epollfd == -1) { perror("epoll_create1"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = listen_sock; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE); } for (;;) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_wait"); exit(EXIT_FAILURE); } for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listen_sock) { conn_sock = accept(listen_sock, (struct sockaddr *) &addr, &addrlen); if (conn_sock == -1) { perror("accept"); exit(EXIT_FAILURE); } setnonblocking(conn_sock); ev.events = EPOLLIN | EPOLLET; ev.data.fd = conn_sock; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } } else { do_use_fd(events[n].data.fd); } } } edge-triggered epoll (EPOLL_CTL_ADD), (EPOLLIN|EPOLLOUT). EPOLLIN EPOLLOUT, epoll_ctl(2) c EPOLL_CTL_MOD. o interest? ( << >> -- ). o , epoll ? , EEXIST. (dup(2), dup2(2), fcntl(2) F_DUPFD) epoll. , events. o epoll ? , epoll? , . , , . o poll/epoll/select epoll? . epoll , . o , epoll ? epoll_ctl(2) (EINVAL). epoll epoll. o epoll UNIX ? , , interest. o interest epoll? , . ( open(2)). dup(2), dup2(2), fcntl(2) F_DUPFD fork(2) . , . interest , , . , , interest, , , . , interest ( epoll_ctl(2) EPOLL_CTL_DEL) . , ( , - dup(2) fork(2)). o epoll_wait(2) , ? . o , ? . . /. o / , EAGAIN EPOLLET ( edge-triggered)? epoll_wait(2) , /. , , EAGAIN () /. -- . / (, , ) / - -- / EAGAIN. (, , FIFO, ) , / / , / / . , read(2) read(2) , , / . write(2) ( , , ). o Starvation (edge-triggered) /, , , (, , epoll). , , . , . o If using an event cache... , epoll_wait(2), , (, ). , 100 epoll_wait(2), 47 , 13 . close(2) 13, , , . , 47, epoll_ctl(EPOLL_CTL_DEL) 13 close(2), . 13, , . Some other systems provide similar mechanisms; for example, FreeBSD has kqueue, and Solaris has /dev/poll. Linux. Linux 2.5.44. glibc 2.3.2. The set of file descriptors that is being monitored via an epoll file descriptor can be viewed via the entry for the epoll file descriptor in the process's /proc/pid/fdinfo directory. See proc(5) for further details. The kcmp(2) KCMP_EPOLL_TFD , epoll. epoll_create(2), epoll_create1(2), epoll_ctl(2), epoll_wait(2), ioctl_eventpoll(2), poll(2), select(2) () Azamat Hackimov , Yuri Kozlov ; GNU (GNU General Public License - GPL, 3 ) , - . - , , () () () <>. Linux 6.9.1 12 2024 . epoll(7)