epoll
— это системный вызов ядра Linux для масштабируемого механизма уведомления о событиях ввода-вывода, впервые представленный в версии 2.5.45 ядра Linux . [1] Его функция — контролировать несколько файловых дескрипторов, чтобы увидеть, возможен ли ввод-вывод на любом из них. Он предназначен для замены старых POSIX и системных вызовов , для достижения лучшей производительности в более требовательных приложениях, где количество отслеживаемых файловых дескрипторов велико (в отличие от старых системных вызовов, которые работают за время O ( n ), работают за O ( 1 раз). [2] select(2)
poll(2)
epoll
epoll
похож на FreeBSD темkqueue
, что состоит из набора функций пользовательского пространства , каждая из которых принимает аргумент дескриптора файла , обозначающий настраиваемый объект ядра, с которым они совместно работают. epoll
использует структуру данных красно-черного дерева (RB-дерево) для отслеживания всех файловых дескрипторов, которые в данный момент отслеживаются. [3]
int epoll_create1 ( int flags );
Создает epoll
объект и возвращает его файловый дескриптор. Этот flags
параметр позволяет изменить поведение epoll. Он имеет только одно допустимое значение: EPOLL_CLOEXEC
. epoll_create()
является более старым вариантом epoll_create1()
и считается устаревшим начиная с версии ядра Linux 2.6.27 и glibc версии 2.9. [4]
int epoll_ctl ( int epfd , int op , int fd , struct epoll_event * event );
Управляет (настраивает), какие файловые дескрипторы отслеживаются этим объектом и за какими событиями. op
может быть ДОБАВИТЬ, ИЗМЕНИТЬ или УДАЛИТЬ.
int epoll_wait ( int epfd , struct epoll_event * events , int maxevents , int timeout );
Ожидает любого из событий, зарегистрированных с помощью epoll_ctl
, пока не произойдет хотя бы одно из них или пока не истечет время ожидания. Возвращает произошедшие события в events
, вплоть до maxevents
сразу. maxevents
— максимальное количество epoll_event
дескрипторов файлов, подлежащих мониторингу. [5] [6] В большинстве случаев maxevents
устанавливается значение размера *events
аргумента ( struct epoll_event *events
массива).
epoll
обеспечивает режимы запуска как по фронту, так и по уровню . В режиме, запускаемом по фронту, вызов epoll_wait
будет возвращаться только тогда, когда новое событие будет поставлено в очередь с epoll
объектом, а в режиме, инициируемом по уровню, epoll_wait
будет возвращаться до тех пор, пока выполняется условие.
Например, если канал , зарегистрированный в системе, epoll
получил данные, вызов epoll_wait
вернется, сигнализируя о наличии данных для чтения. Предположим, считыватель потреблял только часть данных из буфера. В режиме, запускаемом по уровню, дальнейшие вызовы epoll_wait
будут возвращаться немедленно, пока буфер канала содержит данные для чтения. Однако в режиме, запускаемом по фронту, epoll_wait
возврат произойдет только после записи новых данных в канал. [1]
Брайан Кантрилл отметил, что epoll
были ошибки, которых можно было бы избежать, если бы он учился у своих предшественников: порты завершения ввода/вывода , порты событий (Solaris) и kqueue . [7] Однако большая часть его критики была адресована epoll
's EPOLLONESHOT
и EPOLLEXCLUSIVE
options'. EPOLLONESHOT
был добавлен в версию 2.6.2 основной ветки ядра Linux, выпущенную в феврале 2004 г. EPOLLEXCLUSIVE
Был добавлен в версию 4.5, выпущенную в марте 2016 г. [8]