ИМЯ
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:
- EPOLL_CTL_ADD
- Добавить fd
в список interest
и связать
настройки,
указанные
в event, с
внутренним
файлом,
связанным
с fd.
- EPOLL_CTL_MOD
- Изменить
настройки,
связанные
с fd в
списке interest,
на новые,
указанные
в event.
- EPOLL_CTL_DEL
- Удалить
(отменить
регистрацию)
файлового
дескриптора
назначения
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) нуля и
более
следующих
возможных
типов
событий:
- EPOLLIN
- Связанный
файл
доступен
для чтения
с помощью
read(2).
- EPOLLOUT
- Связанный
файл
доступен
для записи
с помощью
write(2).
- EPOLLRDHUP
(начиная с Linux
2.6.17)
- Одна из
сторон
потокового
сокета
закрыла
соединение
или
выключила
записывающую
часть
соединения
(этот флаг
особенно
полезен
при
написании
простого
кода для
обнаружения
отключения
стороны с
помощью
слежения Edge
Triggered).
- EPOLLPRI
- Исключительное
состояние
файлового
дескриптора.
Смотрите
описание
POLLPRI в poll(2).
- EPOLLERR
- Возникло
ошибочное
состояние
связанного
файлового
дескриптора.
Это
событие
также
возникает
на пишущей
стороне
канала,
когда
читающий
конец
закрылся.
Вызов epoll_wait(2)
всегда
будет
сообщать
об этом
событии;
его не
нужно
устанавливать
в events.
- EPOLLHUP
- Произошло
зависание
связанного
файлового
дескриптора.
Вызов epoll_wait(2)
будет
всегда
ждать
этого
события;
его не
нужно
указывать
в events.
- Заметим,
что при
чтении из
канала,
такого как
канал (pipe) или
потоковый
сокет, это
событие
всего-навсего
показывает,
что
партнёр
закрыл
канал со
своего
конца.
Дальнейшее
чтение из
канала
будет
возвращать
0 (конец
файла)
только
после
потребления
всех
неполученных
данных в
канале.
- EPOLLET
- Установить
поведение
Edge Triggered для
связанного
файлового
дескриптора.
Поведение
по
умолчанию
для epoll
равно Level Triggered.
Более
подробное
описание
архитектуры
распределения
событий Edge и
Level Triggered
смотрите в
epoll(7).
- EPOLLONESHOT
(начиная с Linux
2.6.2)
- Установить
однократное
получение
для
связанного
файлового
дескриптора.
Это
означает,
что после
извлечения
события с
помощью
epoll_wait(2) со
связанным
дескриптором
приём
отключается
и о других
событиях
интерфейс
epoll
сообщать
не будет.
Пользователь
должен
вызвать
epoll_ctl() с
операцией
EPOLL_CTL_MOD для
переустановки
новой
маски
событий
для
файлового
дескриптора.
- EPOLLWAKEUP
(начиная с Linux
3.5)
- Если флаги
EPOLLONESHOT и EPOLLET
сброшены и
процесс
имеет
мандат CAP_BLOCK_SUSPEND,
то
убедитесь,
что
система не
находится
в режиме
«suspend» или
«hibernate», пока
это
событие
ожидает
обработки
или
обрабатывается.
Событие
считается
«обрабатывающимся»
начиная с
момента,
когда оно
возвращается
вызовом
epoll_wait(2) и до
следующего
вызова epoll_wait(2)
для того же
файлового
дескриптора
epoll(7),
закрытия
этого
файлового
дескриптора,
удаление
файлового
дескриптора
события с
помощью
EPOLL_CTL_DEL или
сброс EPOLLWAKEUP
для
файлового
дескриптора
события с
помощью
EPOLL_CTL_MOD. Также
смотрите
ДЕФЕКТЫ.
- EPOLLEXCLUSIVE
(начиная с Linux
4.5)
- Установить
единоличный
режим
пробуждения
файлового
дескриптора
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 с той же
парой epfd, fd
вызывает
ошибку.
Вызов epoll_ctl(), в
котором
указан EPOLLEXCLUSIVE
в events и
целевой
файловый
дескриптор
fd в
качестве
экземпляра
epoll, также
вызывает
ошибку. Во
всех
случаях
возникает
ошибка EINVAL.
ВОЗВРАЩАЕМОЕ
ЗНАЧЕНИЕ
При
успешном
выполнении
epoll_ctl()
возвращается
ноль. При
возникновении
ошибок epoll_ctl()
возвращает
-1 и
устанавливает
errno в
соответствующее
значение.
ОШИБКИ
- EBADF
- Значение
epfd или fd не
является
правильным
файловым
дескриптором.
- EEXIST
- Значение op
равно EPOLL_CTL_ADD, и
указанный
файловый
дескриптор
fd уже
зарегистрирован
в данном
экземпляре
epoll.
- EINVAL
- Значение
epfd не
является
файловым
дескриптором
epoll, или
значение fd
равно epfd,
или
запрашиваемая
операция op
не
поддерживается
данным
интерфейсом.
- EINVAL
- Указан
недопустимый
тип
события,
так как в events
установлен
EPOLLEXCLUSIVE.
- EINVAL
- Значение op
равно EPOLL_CTL_MOD и
events
содержит
EPOLLEXCLUSIVE.
- EINVAL
- Значение op
равно EPOLL_CTL_MOD, а
ранее для
этой пары
epfd, fd был
применён
флаг EPOLLEXCLUSIVE.
- EINVAL
- Флаг EPOLLEXCLUSIVE
указан в event
и fd
ссылается
на
экземпляр
epoll.
- ELOOP
- Значение fd
ссылается
на
экземпляр
epoll и эта
операция
EPOLL_CTL_ADD
привела бы
к
зацикливанию
экземпляров
epoll,
отслеживающих
один
другого.
- ENOENT
- В op было
указано
EPOLL_CTL_MOD или EPOLL_CTL_DEL,
а fd не было
зарегистрировано
в данном
экземпляре
epoll.
- ENOMEM
- Недостаточно
памяти для
обработки
запрошенной
управляющей
операции
op.
- ENOSPC
- При
попытке
регистрации
(EPOLL_CTL_ADD) нового
файлового
дескриптора
в
экземпляре
достигнут
предел,
накладываемый
/proc/sys/fs/epoll/max_user_watches.
Подробней
см. в epoll(7).
- EPERM
- Файл
назначения
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.