Pergunta

A Manpage Epoll diz que um FD registrado no Epollet (acionado pela borda) não deve notificar duas vezes o epollin se nenhuma leitura foi feita.
Então, depois de um epollin, você precisa esvaziar o buffer antes que o epoll_wait seja capaz de retornar um novo epollin em novos dados.

No entanto, estou enfrentando problemas com essa abordagem, pois vendo eventos de epollin duplicados para FDs intocados.
Esta é a saída do STRACE, o 0x200 é epollrdhup que ainda não está definido nos meus cabeçalhos glibc, mas definido no kernel.

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

Então, depois de adicionar o número 9 do FD, recebo 2 eventos consecutivos de epollin antes de recuperar o descritor de arquivo, o Syscall Trace mostra como eu excluo o FD antes de ler, mas isso só deve acontecer uma vez, um por evento.
Portanto, não estou lendo a mangueira corretamente ou algo agora está funcionando aqui.

Foi útil?

Solução

Eu acho que você perdeu esta parte do epoll Página do homem:

Como mesmo com o Epoll, múltiplos eventos acionados por arestas podem ser gerados após o recebimento de múltiplos pedaços de dados, o chamador tem a opção de especificar o EPOLLONESHOT Flag, para dizer a Epoll para desativar o descritor de arquivo associado após o recebimento de um evento com epoll_wait(2). Quando o EPOLLONESHOT A bandeira é especificada, é responsabilidade do chamador rearmar o descritor de arquivo usando epoll_ctl(2) com EPOLL_CTL_MOD.

Isto é: você tem dois pedaços de dados chegando na sua fila de recebimento antes do seu primeiro read() Aconteceu, o que significa que você conseguiu dois eventos do Epoll. Parece que EPOLLONESHOT é o que você procura, o que removerá atomicamente o descritor de arquivo do conjunto de pesquisas quando um evento acontecer nele (para que você não precise fazer o EPOLL_CTL_DEL).

Outras dicas

O gatilho de borda significa simplesmente (a menos que você tenha usado o epolloneshot) que você receberá 1 evento quando algo entrar no buffer (kernel).

Assim, se você receber 1 evento epollin e não fizer nada a respeito, você receberá outro epollin na próxima vez que alguns dados chegarem a esse descritor - se nenhum novo dados chegar, você não receberá um evento, mesmo que não Leia todos os dados, conforme indicado pelo primeiro evento.

Bem, para dizer sucintamente, o epolloneshot significa apenas que, se você não ler os dados que deve ler, eles serão descartados.

Normalmente, você seria notificado com um evento para os mesmos dados se não os ler. Com o epolloneshot, no entanto, não ler os dados é perfeitamente legal e eles serão apenas ignorados. Portanto, nenhum evento adicional será gerado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top