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

ИМЯ

epoll_ctl - интерфейс управления файловым дескриптором epoll

ОБЗОР

#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

ОПИСАНИЕ

Данный системный вызов, используется для добавления, изменения или удаления записей в списке interest экземпляра epoll(7), на который указывает файловый дескриптор epfd. Он запрашивает выполнение операции op для файлового дескриптора назначения fd.

Допустимые значения аргумента op:

Добавить fd в список interest и связать настройки, указанные в event, с внутренним файлом, связанным с fd.
Изменить настройки, связанные с fd в списке interest, на новые, указанные в event.
Удалить (отменить регистрацию) файлового дескриптора назначения fd из списка interest. Значение event игнорируется и может быть NULL (но смотрите ДЕФЕКТЫ далее).

Аргумент event описывает объект, связанный с файловым дескриптором fd. Структура 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;        /* Переменная для данных пользователя */
};

Поле events является битовой маской, составляемой из объединяемых (OR) нуля и более следующих возможных типов событий:

Связанный файл доступен для чтения с помощью read(2).
Связанный файл доступен для записи с помощью write(2).
Одна из сторон потокового сокета закрыла соединение или выключила записывающую часть соединения (этот флаг особенно полезен при написании простого кода для обнаружения отключения стороны с помощью слежения Edge Triggered).
Исключительное состояние файлового дескриптора. Смотрите описание POLLPRI в poll(2).
Возникло ошибочное состояние связанного файлового дескриптора. Это событие также возникает на пишущей стороне канала, когда читающий конец закрылся. Вызов epoll_wait(2) всегда будет сообщать об этом событии; его не нужно устанавливать в events.
Произошло зависание связанного файлового дескриптора. Вызов epoll_wait(2) будет всегда ждать этого события; его не нужно указывать в events.
Заметим, что при чтении из канала, такого как канал (pipe) или потоковый сокет, это событие всего-навсего показывает, что партнёр закрыл канал со своего конца. Дальнейшее чтение из канала будет возвращать 0 (конец файла) только после потребления всех неполученных данных в канале.
Установить поведение Edge Triggered для связанного файлового дескриптора. Поведение по умолчанию для epoll равно Level Triggered. Более подробное описание архитектуры распределения событий Edge и Level Triggered смотрите в epoll(7).
Установить однократное получение для связанного файлового дескриптора. Это означает, что после извлечения события с помощью epoll_wait(2) со связанным дескриптором приём отключается и о других событиях интерфейс epoll сообщать не будет. Пользователь должен вызвать epoll_ctl() с операцией EPOLL_CTL_MOD для переустановки новой маски событий для файлового дескриптора.
Если флаги EPOLLONESHOT и EPOLLET сброшены и процесс имеет мандат CAP_BLOCK_SUSPEND, то убедитесь, что система не находится в режиме «suspend» или «hibernate», пока это событие ожидает обработки или обрабатывается. Событие считается «обрабатывающимся» начиная с момента, когда оно возвращается вызовом epoll_wait(2) и до следующего вызова epoll_wait(2) для того же файлового дескриптора epoll(7), закрытия этого файлового дескриптора, удаление файлового дескриптора события с помощью EPOLL_CTL_DEL или сброс EPOLLWAKEUP для файлового дескриптора события с помощью EPOLL_CTL_MOD. Также смотрите ДЕФЕКТЫ.
Установить единоличный режим пробуждения файлового дескриптора epoll, присоединённого к целевому файловому дескриптору fd. При появлении события пробуждения и к целевому файлу присоединены несколько файловых дескрипторов epoll с помощью EPOLLEXCLUSIVE, то события получат один или несколько файловых дескрипторов epoll через epoll_wait(2). По умолчанию в этом случае (если EPOLLEXCLUSIVE не установлен) все файловые дескрипторы epoll получают событие. Таким образом EPOLLEXCLUSIVE в некоторых случаях помогает избежать проблем стадной работы.
Если один файловый дескриптор указан в нескольких экземплярах epoll, и одни имеют флаг EPOLLEXCLUSIVE, а другие нет, то события получат все экземпляры epoll, у которых не указан EPOLLEXCLUSIVE, и, как минимум, один экземпляр epoll, у которого есть задан EPOLLEXCLUSIVE.
Следующие значения можно указывать вместе с EPOLLEXCLUSIVE: EPOLLIN, EPOLLOUT, EPOLLWAKEUP и EPOLLET. Также можно указывать EPOLLHUP и EPOLLERR, но они не обязательны: как обычно, события всегда приходят, если они возникают, независимо указаны ли они в events. При указании других значений в events возникает ошибка EINVAL.
EPOLLEXCLUSIVE можно использовать только в операции EPOLL_CTL_ADD; попытка использовать его в EPOLL_CTL_MOD вызывает ошибку. Если EPOLLEXCLUSIVE установлен с помощью epoll_ctl(), то последующая EPOLL_CTL_MOD с той же парой epfdfd вызывает ошибку. Вызов epoll_ctl(), в котором указан EPOLLEXCLUSIVE в events и целевой файловый дескриптор fd в качестве экземпляра epoll, также вызывает ошибку. Во всех случаях возникает ошибка EINVAL.

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

При успешном выполнении epoll_ctl() возвращается ноль. При возникновении ошибок epoll_ctl() возвращает -1 и устанавливает errno в соответствующее значение.

ОШИБКИ

Значение epfd или fd не является правильным файловым дескриптором.
Значение op равно EPOLL_CTL_ADD, и указанный файловый дескриптор fd уже зарегистрирован в данном экземпляре epoll.
Значение epfd не является файловым дескриптором epoll, или значение fd равно epfd, или запрашиваемая операция op не поддерживается данным интерфейсом.
Указан недопустимый тип события, так как в events установлен EPOLLEXCLUSIVE.
Значение op равно EPOLL_CTL_MOD и events содержит EPOLLEXCLUSIVE.
Значение op равно EPOLL_CTL_MOD, а ранее для этой пары epfdfd был применён флаг EPOLLEXCLUSIVE.
Флаг EPOLLEXCLUSIVE указан в event и fd ссылается на экземпляр epoll.
Значение fd ссылается на экземпляр epoll и эта операция EPOLL_CTL_ADD привела бы к зацикливанию экземпляров epoll, отслеживающих один другого.
В op было указано EPOLL_CTL_MOD или EPOLL_CTL_DEL, а fd не было зарегистрировано в данном экземпляре epoll.
Недостаточно памяти для обработки запрошенной управляющей операции op.
При попытке регистрации (EPOLL_CTL_ADD) нового файлового дескриптора в экземпляре достигнут предел, накладываемый /proc/sys/fs/epoll/max_user_watches. Подробней см. в epoll(7).
Файл назначения fd не поддерживает epoll. Эта ошибка может возникнуть, если fd ссылается на, например, обычный файл или каталог.

ВЕРСИИ

Системный вызов epoll_ctl() был добавлен в ядро версии 2.6.

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

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

ЗАМЕЧАНИЯ

Интерфейс epoll поддерживает все файловые дескрипторы, которые поддерживает poll(2).

ДЕФЕКТЫ

В ядрах до версии 2.6.9 для операции EPOLL_CTL_DEL в event требовался указатель со значением не равным null, хотя этот аргумент игнорировался. Начиная с Linux 2.6.9, при EPOLL_CTL_DEL в event можно указывать NULL. В переносимых приложениях, которые должны быть работоспособными в системах на ядрах до 2.6.9, в event нужно указывать указатель со значением не равным null.

Если в flags указан EPOLLWAKEUP, но вызывающий не имеет мандата CAP_BLOCK_SUSPEND, то флаг EPOLLWAKEUP просто игнорируется. Такое неуместное поведение необходимо, так как в первоначальной реализации не выполнялась проверка корректности аргумента flags, и добавление EPOLLWAKEUP с проверкой того, что вызов завершился с ошибкой, если вызывающий не имеет мандата CAP_BLOCK_SUSPEND, привело к поломке не одного существующего пользовательского приложения, которое произвольно устанавливало (и зря) этот бит. Корректное приложение должно дважды проверить, что имеет мандат CAP_BLOCK_SUSPEND, если пытается использовать флаг EPOLLWAKEUP.

СМОТРИТЕ ТАКЖЕ

epoll_create(2), epoll_wait(2), poll(2), epoll(7)

2019-03-06 Linux