epoll — это механизм уведомления о событиях ввода-вывода, который представляет собой Linux Реализация мультиплексирования ввода-вывода в ядре. Мультиплексирование ввода-вывода означает одновременный мониторинг нескольких источников ввода и вывода в одной операции с возвратом, когда один или несколько источников ввода и вывода доступны, а затем выполнение над ними операций чтения и записи.
epoll имеет два способа работы: Триггер уровня LT и триггер ET-edge (режим работы по умолчанию), основные отличия заключаются в следующем:
LT, ядро уведомит вас, готов ли fd. Если он не обработан, оно продолжит вас уведомлять. При использовании ET ядро уведомляет только один раз.
Что такое ввод-вывод?
Объектом ввода/вывода может быть файл, Сеть (сокет), пайп (pipe) между процессами. В системах Linux они представлены файловыми дескрипторами (fd).
Что такое событие?
Поведения, связанные с вводом-выводом, такие как установление соединений, операции чтения, операции записи и т. д., абстрагируют концепцию, то есть события, которые представлены классом SelectionKey.java в jdk, например: читаемые события, когда ядро буфер чтения, связанный с дескриптором файла. Если область доступна для чтения, запускается событие чтения (доступно для чтения: буфер ядра не пуст и есть данные, которые можно прочитать, событие, доступное для записи, запускается, когда буфер записи ядра связан с ним); файловый дескриптор доступен для записи, срабатывает записываемое событие (может быть Write: буфер ядра не заполнен, есть свободное место для записи).
Что такое механизм уведомления?
Механизм уведомления предназначен для упреждающего уведомления о возникновении события. Противоположностью механизма уведомления является механизм опроса.
Параметр size сообщает ядру приблизительное количество событий, которые обрабатывает этот объект epoll, а не максимальное количество, которое может быть обработано.
В текущей версии Linux от этой функции размера отказались (но не передавайте 0 для размера, иначе будет сообщено об ошибке недопустимого аргумента).
Ядро сгенерирует структуру данных экземпляра epoll и вернет дескриптор файла. Этот специальный дескриптор является дескриптором экземпляра epoll. Последующие операции с epoll должны идентифицировать объект epoll через дескриптор.
Язык кода:javascript
копировать
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
Добавьте отслеживаемый дескриптор в красно-черное дерево или удалите его из красно-черного дерева или измените событие прослушивания.
Возврат: 0 указывает на успех, -1 указывает на ошибку, а тип ошибки определяется на основе кода ошибки errno.
описание параметра op тип операции:
EPOLL_CTL_ADD: добавьте дескриптор, который необходимо отслеживать, в список интересов.
EPOLL_CTL_DEL: удалить дескриптор из списка интересов.
EPOLL_CTL_MOD: изменить дескриптор в списке интересов.
Значение epoll_event:
ЭПОЛЛИН: дескриптор доступен для чтения
EPOLLOUT: дескриптор доступен для записи.
EPOLLET: установите режим уведомления о событиях epoll на срабатывание по фронту
EPOLLONESHOT: уведомить в первый раз, затем больше не отслеживать
EPOLLHUP: локальный дескриптор генерирует событие зависания, а событием мониторинга по умолчанию является
EPOLLRDHUP: дескриптор узла генерирует событие зависания.
EPOLLPRI: запускается внеполосными данными
EPOLLERR: срабатывает при возникновении ошибки в дескрипторе. Событие обнаруживается по умолчанию.
Язык кода:javascript
копировать
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
Блокирует ожидание зарегистрированных событий, возвращает количество событий и записывает инициированные события в массив событий.
события: используется для записи триггерных событий, его размер должен соответствовать maxevents.
maxevents: максимальное количество возвращаемых событий
Параметр timeout описывает верхний предел времени блокировки при вызове функций, единица измерения — мс:
timeout = -1 означает, что вызов будет блокироваться до тех пор, пока дескриптор файла не перейдет в состояние готовности или пока не будет перехвачен сигнал перед возвратом;
timeout = 0 используется для неблокирующего определения того, находится ли дескриптор в состоянии готовности. Независимо от результата, вызов немедленно возвращается;
timeout > 0 означает, что вызов будет длиться до истечения времени ожидания. Если объект обнаружения станет готовым или будет захвачен сигнал в течение этого периода, он вернется, в противном случае он не будет ждать истечения времени ожидания.
3. Иллюстрация принципа epoll
1. Вызвав epoll_create, создайте файловый узел в файловой системе epoll, откройте собственную область высокоскоростного кэша ядра epoll, установите красно-черное дерево, выделите объекты памяти желаемого размера и создайте связанный список для хранения. подготовка. Готовое мероприятие.
2. Вызвав epoll_ctl, поместите отслеживаемый сокет в соответствующее красно-черное дерево, зарегистрируйте функцию обратного вызова для обработчика прерываний ядра и уведомите ядро, что в случае поступления данных этого дескриптора поместите его в список готовности.
3. Вызвав epoll_wait, проверьте, есть ли данные в списке готовности, а затем извлеките и очистите список готовности, что очень эффективно.
4. Сравнение epoll, select и poll
1. Как пользовательский режим передает файловые дескрипторы ядру
выберите: Создайте 3 набора файловых дескрипторов и скопируйте их в ядро для мониторинга чтения, записи и аномальных действий соответственно. Это ограничение ограничено количеством файловых файлов, которые может открыть один процесс. Значение по умолчанию — 1024.
poll: Скопируйте входящий массив структур struct pollfd в ядро для мониторинга.
Структура структуры следующая:
epoll: Выполнение epoll_create создаст красно-черное дерево и готовый связанный список (в этом связанном списке хранятся готовые дескрипторы файлов) в области высокоскоростного кэша ядра. Затем функция epoll_ctl, выполняемая пользователем для добавления дескриптора файла, добавит соответствующий узел в красно-черное дерево.
2. Как определить статус чтения и записи файловых дескрипторов в режиме ядра
select: использовать режим опроса для обхода всех fd и, наконец, вернуть маску, указывающую, готовы ли операции чтения и записи дескриптора, и присвоить значение fd_set на основе этой маски.
опрос: тот же метод опроса используется для запроса статуса каждого fd. Если все готово, добавьте элемент в очередь ожидания и продолжите обход.
epoll: использовать механизм обратного вызова. При выполнении операции добавления epoll_ctl не только дескриптор файла помещается в красно-черное дерево, но также регистрируется функция обратного вызова. Когда ядро обнаруживает, что дескриптор файла доступен для чтения/записи, оно вызывает функцию обратного вызова. Функция обратного вызова будет. Дескриптор файла будет помещен в список готовых.
3. Найдите готовый дескриптор файла и передайте его в пользовательский режим.
select: перевести ранее переданную копию fd_set в пользовательский режим и вернуть общее количество готовых файловых дескрипторов. Пользовательский режим не знает, какие файловые дескрипторы находятся в состоянии готовности, и для определения их необходимо просмотреть.
опрос: то же, что и метод выбора.
epoll: epoll_wait нужно только проверить, есть ли данные в готовом связанном списке, и, наконец, возвращает данные связанного списка в массив и возвращает количество готовых элементов. Ядро помещает готовые дескрипторы файлов во входящий массив, поэтому его нужно только последовательно обходить и обрабатывать. Возвращаемый здесь дескриптор файла передается через mmap, чтобы позволить ядру и пользовательскому пространству использовать одну и ту же память, уменьшая количество ненужных копий.
5. Резюме
1. Действия select и poll в основном одинаковы, за исключением того, что poll использует связанный список для хранения дескрипторов файлов, тогда как select использует для хранения бит метки fd, поэтому select будет ограничен максимальным количеством соединений, но poll будет нет.
2. Хотя select, poll и epoll вернут количество готовых файловых дескрипторов. Но select и poll не указывают четко, какие дескрипторы файлов готовы, а epoll это делает. Разница в том, что после возврата системного вызова программа, вызывающая select и poll, должна пройти весь отслеживаемый дескриптор файла, чтобы выяснить, кто готов, в то время как epoll может справиться с этим напрямую.
3. Выберите и опросите, используя опрос, чтобы проверить, готов ли файловый дескриптор, в то время как epoll использует механизм обратного вызова. В результате по мере увеличения fd эффективность выбора и опроса будет снижаться линейно, в то время как на epoll это не сильно повлияет, если не будет много активных сокетов.
4. Режим запуска по краю epoll очень эффективен, и система не будет перегружена большим количеством ненужных готовых файловых дескрипторов.
5. И select, и poll должны скопировать структуру данных, связанную с файловым дескриптором, в ядро и, наконец, скопировать ее. Структура данных, связанная с файловым дескриптором, созданная самим epoll, сохраняется в состоянии ядра. При возврате системного вызова память сопоставления файлов mmap() используется для ускорения передачи сообщений в пространстве ядра: то есть epoll использует mmap для сокращения. копирование накладных расходов.
Заявление об авторских правах: Содержание этой статьи добровольно предоставлено пользователями Интернета, а мнения, выраженные в этой статье, представляют собой только точку зрения автора. Данный сайт лишь предоставляет услуги по хранению информации, не имеет никаких прав собственности и не несет соответствующей юридической ответственности. Если вы обнаружите на этом сайте какое-либо подозрительное нарушение авторских прав/незаконный контент, отправьте электронное письмо, чтобы сообщить. После проверки этот сайт будет немедленно удален.
Издатель: Full stack программист и руководитель стека. Пожалуйста, укажите источник для перепечатки: https://javaforall.cn/230882.html Исходная ссылка: https://javaforall.cn.