Как событие сокета распространяется/преобразуется в epoll?

Мне любопытно, как epoll_wait() получает событие о том, что зарегистрированный сокет (с помощью epoll_ctl()) готов для чтения/записи.

Я считаю, что glibc волшебным образом справляется с этим.

Тогда есть ли документ, описывающий, как следующие события могут быть вызваны для сокета?

  1. ЭПОЛЛПРИ
  2. ЭПОЛЛРДНОРМ
  3. EPOLLRDBAND
  4. ЭПОЛЛВРНОРМ
  5. EPOLLWRBAND
  6. ЭПОЛЛМСГ
  7. ЭПОЛЛЕРР
  8. ЭПОЛХУП
  9. ЭПОЛЛРДХУП

P.S. Первоначально я пытался вставить перечисление EPOLL_EVENTS в sys/epoll.h на свой ящик здесь; stackoverflow считает, что я неправильно отформатировал блок кода, хотя я обернул его тегом pre, а затем code, есть идеи?


person Hei    schedule 07.08.2013    source источник
comment
Epoll выполняет всю критическую работу в ядре, как хорошо объясняет этот пост: stackoverflow.com/questions/5383959/ ... какую именно проблему вы пытаетесь решить?   -  person Shafik Yaghmour    schedule 07.08.2013
comment
@ShafikYaghmour Вы должны переместить свой комментарий в ответ.   -  person This isn't my real name    schedule 08.08.2013
comment
Я предполагаю, что это обработчик прерывания: notes.shichao.io/lkd/ch7   -  person apporc    schedule 11.04.2019


Ответы (2)


Самая вопиющая проблема с документацией epoll заключается в том, что в ней не указано жирным шрифтом, что события epoll на самом деле полностью идентичны событиям poll (2). Действительно, на стороне ядра epoll обрабатывает свои события с точки зрения более старых имен событий poll:

#define POLLIN     0x0001  // EPOLLIN
#define POLLPRI    0x0002  // EPOLLPRI
#define POLLOUT    0x0004  // EPOLLOUT
#define POLLERR    0x0008  // EPOLLERR
#define POLLHUP    0x0010  // EPOLLHUP
#define POLLNVAL   0x0020  // unused in epoll
#define POLLRDNORM 0x0040  // EPOLLRDNORM
#define POLLRDBAND 0x0080  // EPOLLRDBAND
#define POLLWRNORM 0x0100  // EPOLLWRNORM
#define POLLWRBAND 0x0200  // EPOLLWRBAND
#define POLLMSG    0x0400  // EPOLLMSG
#define POLLREMOVE 0x1000  // unused in epoll
#define POLLRDHUP  0x2000  // EPOLLRDHUP

Затем краткий просмотр исходного кода ядра показывает, что:

  • EPOLLIN и EPOLLRDNORM идентичны (epoll возвращает EPOLLIN | EPOLLRDNORM, когда данные доступны для чтения из файлового дескриптора).

  • EPOLLOUT и EPOLLWRNORM идентичны (epoll возвращает EPOLLOUT | EPOLLWRNORM, когда место в буфере доступно для записи).

  • EPOLLRDBAND и EPOLLWRBAND сигнализируют о наличии внеполосных данных в дескрипторе (на некоторых сокетах это будут данные, отправленные с флагом MSG_OOB, переданным сокету).

  • EPOLLPRI — это флаг модификатора, который всегда дополняет какое-либо другое событие (например, EPOLLERR). Его использование зависит от подсистемы, так как это может означать несколько разные вещи в зависимости от того, для какой цели служит связанный файловый дескриптор.

  • EPOLLMSG кажется неиспользуемым ядром и не служит никакой цели.

  • EPOLLRDHUP сигнализирует о том, что одноранговый узел закрыл свою сторону канала для чтения, но все еще может получать данные (удобно, чтобы установить, что данные запроса больше не поступают).

  • EPOLLHUP сигнализирует о том, что партнер закрыл свою сторону канала.

person oakad    schedule 26.11.2014

Вся критическая работа для epoll выполняется в ядре, API пользовательского пространства — это просто интерфейс. Предыдущий поток на тему Почему ePoll масштабируется лучше, чем Poll? раскрывает подробности того, как ядро ​​реализует epoll приятные подробности.

Что касается документа, описывающего события и то, как они инициируются, epoll_ctl(2) man page охватывает каждое событие, например:

EPOLLIN
          The associated file is available for read(2) operations.

EPOLLOUT
          The associated file is available for write(2) operations.

Для лучшего описания EPOLLET вам необходимо прочитать epoll(7) man page. .

Это полный пример того, как использовать epoll.

Вы используете epoll_ctl, чтобы запросить, какие события вы хотите получать события EPOLLIN и EPOLLET, приведенный выше код делает это:

event.events = EPOLLIN | EPOLLET;
s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
person Shafik Yaghmour    schedule 07.08.2013
comment
Мои вопросы заключаются в том, что есть много других возможных событий (как я перечислил в своих первоначальных вопросах). Тем не менее, нет документа, в котором упоминается, в какой ситуации каждый тип события в сокете будет распространяться на epoll_wait(). Давайте возьмем пример, что произойдет с сокетом, который epoll_wait() получит EPOLLRDNORM? - person Hei; 08.08.2013
comment
Кстати, хотя ваша ссылка не отвечает на мой вопрос, в ней есть много полезной информации. Спасибо, что поделились Шафиком! - person Hei; 08.08.2013
comment
@Hei, я уточню, вы используете epoll_ctl, чтобы запросить, какое из событий вы хотите получать, я добавлю ссылку на пример кода. - person Shafik Yaghmour; 08.08.2013
comment
Привет, Шафик, я думаю, ты неправильно истолковал мой вопрос. Давайте придерживаться того, что вы только что добавили. Допустим, я установил для event.events значение EPOLLIN | ЭПОЛЛЕ | ЭПОЛЛРДНОРМ. Тогда когда я получу EPOLLRDNORM? Я думаю, что возможный ответ: 1. никогда (тогда почему? в любом документе так написано?). 2. когда происходит x (тогда так написано в любом документе?). Мой главный вопрос заключается в том, что в epoll.h указано много событий, но я не вижу ни одного документа, в котором говорилось бы о некоторых из тех, которые я перечислил в своем исходном вопросе. - person Hei; 09.08.2013
comment
@Hei У меня было несколько ссылок, я думал, что та, на которую я ссылался, охватывает их все, но эта, кроме одной, выглядит так: turing.com.br/pydoc/2.7/library/select.html позвольте мне посмотреть, смогу ли я найти лучший - person Shafik Yaghmour; 09.08.2013