EPOLL_CTL_ADD | Файловый дескриптор fd добавляется к набору файловых дескрипторов набором событий events . Если файловый дескриптор уже присутствует, он возвращает EEXIST . (Несколько потоков могут добавлять тот же файловый дескриптор к набору epoll более одного раза, но это действие ничего не меняет.) |
EPOLL_CTL_DEL | Файловый дескриптор fd удаляется из контролируемого набора файловых дескрипторов. Параметр events должен указывать на struct epoll_event , но содержимое этой структуры игнорируется. (Это еще раз доказывает, что events должен быть допустимым указателем; он не может быть NULL .) |
EPOLL_CTL_MOD | Системный вызов struct epoll_event для fd обновляется на основе информации, на которую указывает events . Это позволяет контролировать набор событий и обновлять элемент данных, ассоциируемый с файловым дескриптором, не создавая условий состязания. |
Последним системным вызовом epoll
является epoll_wait()
, который блокирует до тех пор, пока один или несколько контролируемых файловых дескрипторов не будут иметь данные для чтения или же не будут готовы к записи. Первым аргументом является дескриптор epoll
, а последний — тайм-аутом в секундах. Если файловые дескрипторы не готовы к обработке до истечения тайм-аута, epoll_wait()
возвращает 0
.
Два промежуточных параметра определяют буфер для ядра, в который можно копировать структуры struct epoll_event
. Параметр events
указывает на буфер, maxevents
определяет, какое количество структур struct epoll_event
помещается в буфер, а возвращаемое значение сообщает программе количество структур, помещенных в этот буфер (пока вызов не попадет в состояние тайм-аута либо не произойдет ошибка).
Каждый системный вызов struct epoll_event
сообщает программе полное состояние контролируемого файлового дескриптора. Элемент events
может иметь установленные флаги EPOLLIN
, EPOLLOUT
или EPOLLPRI
, а также два новых флага, которые описаны ниже.
EPOLLERR | С файлом связано ожидающее состояние ошибки; это случается, если ошибка происходит в сокете, когда приложение не считывает из него или не записывает в него. |
EPOLLHUP | Файловый дескриптор завис; в главе 10 дана информация о том, когда это обычно происходит. |
На первый взгляд это все может показаться сложным, но на самом деле это очень похоже на работу poll()
. Вызов epoll_create()
— это то же, что и распределение массива struct pollfd
, a epoll_ctl()
— это то же, что и инициализация элементов этого массива. Главный цикл, обрабатывающий файловые дескрипторы, использует epoll_wait()
вместо системного вызова poll()
, а close()
аналогичен освобождению памяти, занимаемой массивом struct pollfd
. Эти параллели помогают переписывать с применением epoll
программы мультиплексирования, которые изначально были реализованы с помощью poll()
или select()
.
Интерфейс epoll
предлагает еще одну возможность, которую невозможно сравнить с poll()
или select()
. Поскольку дескриптор epoll
в действительности является файловым дескриптором (вот почему его можно передавать close()
), имеется возможность контролировать дескриптор epoll
как часть еще одного дескриптора epoll
либо через poll()
или select()
. Дескриптор epoll
будет готов к чтению из любого места, а вызов epoll_wait()
вернет события.
В окончательном решении проблемы мультиплексирования каналов, предложенном в данном разделе, используется epoll
. Оно очень похоже на другие примеры, вот только определенная часть кода инициализации перемещена в новую функцию addEvent()
для предотвращения нежелательного удлинения программы.
1: /* mpx-epoll.c */
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8:
9: #include
10: