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) . If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in step 5 will probably hang despite the available data still present in the file input buffer; meanwhile the remote peer might be expecting a response based on the data it already sent. The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor, that is, an event will be generated upon each receipt of a chunk of data. So, in step 5 the caller might end up waiting for some data that is already present inside the input buffer. In the above example, an event on rfd will be generated because of the write done in 2 and the event is consumed in 3. Since the read operation done in 4 does not consume the whole buffer data, the call to epoll_wait(2) done in step 5 might block indefinitely. , 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 , Kirill Rekhov ; GNU (GNU General Public License - GPL, 3 ) , - . - , , () () () <>. Linux man-pages 6.12 21 2024 . epoll(7)