Epoll в режиме EPOLLET возвращая 2 эполлина перед чтением от розетки

StackOverflow https://stackoverflow.com/questions/2673890

Вопрос

EPOLL MANPAGE говорит, что FD зарегистрирован с EPOLLET (срабатывает на краем), не должен уведомить дважды эполлин, если нет прочитанного.
Поэтому после эполлина необходимо опустошить буфер до того, как EPoll_Wait может вернуть новый эполлин на новые данные.

Однако я испытываю проблемы с этим подходом, когда я вижу дублированные события эполлина для нетронутых FDS.
Это выходная мощность, 0x200 - EpollRdhup, который еще не определен в моих заголовках Glibc, а определен в ядре.

30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET|0x2000, {u32=9, u64=9}}) = 0
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3,  <unfinished ...>
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = 0
30306 recv(9, "7u\0\0\10\345\241\312\t\20\f\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30"..., 20000, 0) = 20000
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = -1 ENOENT (No such file or directory)
30305 recv(9, " \31(C0\17\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30\200\10 \31("..., 20000, 0) = 10011

Итак, после добавления FD Number 9, я получаю 2 последовательных события Epollin, прежде чем погибать дескриптор файла, трассировка SYSCall показывает, как я удаляю FD перед чтением, но он должен произойти только один раз, по одному на мероприятие.
Итак, либо я не читаю должным образом, или что-то здесь работает.

Это было полезно?

Решение

Я думаю, что вы пропустили эту часть epoll Страница человека:

Поскольку даже с срабатыванием на краю EPOLL несколько событий могут быть сгенерированы при получении нескольких кусочков данных, вызывающий абонент имеет возможность указать EPOLLONESHOT Флаг, чтобы сказать EPoll, чтобы отключить связанный файл дескриптор после получения события с epoll_wait(2). Отказ Когда EPOLLONESHOT Указана флаг, ответственность вызывающего абонента за перевооружение дескриптора файла, используя epoll_ctl(2) с участием EPOLL_CTL_MOD.

То есть: у вас есть два кусочка данных, прибывающих в вашу доступную очередь до первого read() случилось, что означает, что у вас есть два события EPOLL. Это выглядит как EPOLLONESHOT Это то, что вы после того, как атомно удаляют дескриптор файла из набора опроса, когда событие происходит на нем (так что вам не нужно делать EPOLL_CTL_DEL).

Другие советы

Edge Trigger просто означает (если вы не использовали Epolloneshot), что вы получите 1 событие, когда что-то входит в буфер (ядра).

Таким образом, если вы получите 1 событие Epollin и ничего не сделаете об этом, вы получите еще один эполлин в следующий раз, когда некоторые данные поступают в этот дескриптор - если новые данные не прибудут, вы не получите событие, даже если вы не сделали Прочитайте любые данные, как указано первым событием.

Ну, чтобы кратко положить, Epolloneshot просто означает, что если вы не читаете данные, которые вы должны читать, они будут отброшены.

Обычно вы будете уведомлены с событием для тех же данных, если вы их не читаете. Однако с Epolloneshot не читают данные, совершенно законные, и они будут просто проигнорированы. Следовательно, дальнейшие события не будут сгенерированы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top