Epoll (Epoll)

Перейти к навигации Перейти к поиску

Epoll (event poll) — API мультиплексированного ввода-вывода, предоставляемого Linux для приложений. API позволяет приложениям осуществлять мониторинг нескольких открытых файловых дескрипторов (которые могут быть файлами, устройствами или сокетами, в том числе сетевыми), для того, чтобы узнать, готово ли устройство для продолжения ввода (вывода). Epoll планировался как более эффективная замена вызовам select() и poll(), определёнными в POSIX. Epoll может предоставить более эффективный механизм для приложений, обрабатывающих большое количество одновременно открытых соединений — со сложностью O(1) в отличие от стандартного механизма, обладающего сложностью O(n). Epoll аналогичен системе Kqueue из FreeBSD и также представляет собой объект ядра, предоставляемый для работы в пространстве пользователя в виде файлового дескриптора.

По аналогии "epoll" часто называют другие подобные решения, схожие по методике.

Проблема select/poll

[править | править код]

Для использования select или poll приложение должно передать в ядро полный список всех файловых дескрипторов, в которых оно ожидает появление данных; а ядро, в свою очередь, должно для каждого из переданных элементов проверить состояние дескрипторов и сформировать структуру, описывающую состояние каждого переданного дескриптора. Такой подход не создаст много проблем в условиях десятков или сотен дескрипторов. Тем не менее, производительность в больших сетях заметно падает.

Описание epoll API

[править | править код]

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

  • epoll_create() — создаёт структуру данных (epoll instance), с которой в дальнейшем идёт работа. Структура одна для всех файловых дескрипторов, за которыми идёт наблюдение. Функция возвращает файловый дескриптор, который в дальнейшем передаётся во все остальные вызовы epoll API.
  • epoll_ctl() — используется для управления epoll instance, в частности, позволяет выполнять операции EPOLL_CTL_ADD (добавление файлового дескриптора к наблюдению), EPOLL_CTL_DEL (удаление файлового дескриптора из наблюдения), EPOLL_CTL_MOD (изменение параметров наблюдения), EPOLL_CTL_DISABLE (добавлена в Linux 3.7) — для безопасного отключения наблюдения за файловым дескриптором в многопоточных приложениях
  • epoll_wait() — возвращает количество (один или более) файловых дескрипторов из списка наблюдения, у которых поменялось состояние (которые готовы к вводу-выводу).
Прототипы функций

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

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

События, за которыми можно наблюдать с помощью epoll:

  • EPOLLIN — новые данные (для чтения) в файловом дескрипторе
  • EPOLLOUT — файловый дескриптор готов продолжить принимать данные (для записи)
  • EPOLLERR — в файловом дескрипторе произошла ошибка
  • EPOLLHUP — закрытие файлового дескриптора

Режимы работы

[править | править код]

epoll позволяет работать в двух режимах:

  • edge-triggered — файловый дескриптор с событием возвращается, только если с момента последнего возврата произошли новые события (например, пришли новые данные)
  • level-triggered — файловый дескриптор возвращается, если остались непрочитанные/записанные данные

Если приложение прочитало из файлового дескриптора только часть доступных для чтения данных, то при следующем вызове:

  • в edge-triggered файловый дескриптор не будет возвращён до тех пор, пока в дескрипторе не появятся новые данные;
  • в level-triggered файловый дескриптор будет возвращаться до тех пор, пока не прочитаны все «старые» данные (и новые, если таковые придут)

Управление

[править | править код]

Начиная с 2.6.28 /proc/sys/fs/epoll/max_user_watches указывает максимальное число файловых дескрипторов, за которыми может наблюдать пользователь.