Scroll to navigation

EPOLL_WAIT(2) Руководство программиста Linux EPOLL_WAIT(2)

ИМЯ

epoll_wait, epoll_pwait - ждать события ввода/вывода на файловом дескрипторе epoll

СИНТАКСИС

#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events,
               int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events,
               int maxevents, int timeout,
               const sigset_t *sigmask);

ОПИСАНИЕ

The epoll_wait() system call waits for events on the epoll(7) instance referred to by the file descriptor epfd. The buffer pointed to by events is used to return information from the ready list about file descriptors in the interest list that have some events available. Up to maxevents are returned by epoll_wait(). The maxevents argument must be greater than zero.

В аргументе timeout указывается количество миллисекунд, на которые будет заблокирован epoll_wait(). Время отслеживается по часам CLOCK_MONOTONIC.

A call to epoll_wait() will block until either:

  • событие не будет доставлено в файловый дескриптор;
  • вызов не прервётся обработчиком сигнала;
  • не истечёт время ожидания.

Заметим, что интервал timeout будет округлён в соответствии с точностью системных часов, а задержки ядерного планирования приведут к тому, что интервал блокировки может быть немного больше. Если присвоить timeout значение -1, то epoll_wait() блокируется навсегда; если значение timeout равно 0, то epoll_wait() сразу завершает работу, даже если никаких событий не произошло.

Структура struct epoll_event определена так:


typedef union epoll_data {

void *ptr;
int fd;
uint32_t u32;
uint64_t u64; } epoll_data_t; struct epoll_event {
uint32_t events; /* События epoll */
epoll_data_t data; /* Переменная для данных пользователя */ };

The data field of each returned epoll_event structure contains the same data as was specified in the most recent call to epoll_ctl(2) (EPOLL_CTL_ADD, EPOLL_CTL_MOD) for the corresponding open file descriptor.

The events field is a bit mask that indicates the events that have occurred for the corresponding open file description. See epoll_ctl(2) for a list of the bits that may appear in this mask.

epoll_pwait()

Отношения между epoll_wait() и epoll_pwait() аналогичны родству select(2) и pselect(2): как pselect(2), epoll_pwait() позволяет приложению безопасно ждать, пока файловый дескриптор не станет готов или пока не будет получен сигнал.

Вызов epoll_pwait():


ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);

эквивалентен атомарному выполнению следующих вызовов:


sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = epoll_wait(epfd, &events, maxevents, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);

Аргумент sigmask может быть равен NULL — в этом случае epoll_pwait() эквивалентен epoll_wait().

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При нормальном выполнении epoll_wait() возвращает количество файловых дескрипторов, готовых для запросов ввода-вывода, или ноль, если ни один файловый дескриптор не стал готов за отведённые timeout миллисекунд. При возникновении ошибки epoll_wait() возвращает -1 и устанавливает errno в соответствующее значение.

ОШИБКИ

Значение epfd не является правильным файловым дескриптором.
Память, указанная events, недоступна на запись из-за прав доступа.
Вызов был прерван обработчиком сигнала до возникновения любого из запрошенных событий или истечения timeout; см. signal(7).
epfd не является файловым дескриптором epoll, или maxevents меньше или равно нулю.

ВЕРСИИ

Вызов epoll_wait() был добавлен в ядро версии 2.6. В glibc соответствующая функция появилась в версии 2.3.2.

Вызов epoll_pwait() был добавлен в ядро Linux 2.6.19. В glibc соответствующая функция появилась в версии 2.6.

СООТВЕТСТВИЕ СТАНДАРТАМ

Вызов epoll_wait() есть только в Linux.

ЗАМЕЧАНИЯ

Пока одна нить блокирована в вызове epoll_wait(), в другой нити возможно добавить файловый дескриптор, который будет ожидаться экземпляром epoll. Как только новый файловый дескриптор станет готовым, это разблокирует вызов epoll_wait().

Если готово более maxevents файловых дескрипторов при вызове epoll_wait(), то последующие вызовы epoll_wait() циклически обработают весь набор готовых файловых дескрипторов. Такое поведение помогает избежать голодания — когда процесс не уведомляется, что дополнительные файловые дескрипторы готовы, так как он нацелен на набор файловых дескрипторов, про которые уже известно об их готовности.

Заметим, что возможно вызвать epoll_wait() для экземпляра epoll, чей список interest ещё пуст (или чей список interest станет пустым, так как файловые дескрипторы закрыты или удалены из interest в другой нити). Вызов будет заблокирован до тех пор, пока какой-нибудь файловый дескриптор не будет добавлен в список interest (в другой нити) и этот файлоый дескриптор не станет готовым.

ДЕФЕКТЫ

В ядрах до версии 2.6.37, если значение timeout больше чем приблизительное LONG_MAX / HZ секунд, то оно воспринимается как -1 (т.е., бесконечность). То есть, например, в системе, где sizeof(long) равно 4 и значение ядра HZ равно 1000, задержка более 35,79 минут считается бесконечностью.

Отличия между библиотекой C и ядром

Ядерный системный вызов epoll_pwait() имеет шестой аргумент, size_t sigsetsize, в котором указывается размер аргумента sigmask в байтах. В обёрточной функции glibc epoll_pwait() в этом аргументе передаётся постоянная величина (равная sizeof(sigset_t)).

СМ. ТАКЖЕ

epoll_create(2), epoll_ctl(2), epoll(7)

ЗАМЕЧАНИЯ

Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.

ПЕРЕВОД

Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.

11 апреля 2020 г. Linux