Domanda

La pagina del manuale epoll dice che un fd registrato con EPOLLET (fronte attivato) non dovresti avvisare EPOLLIN due volte se non di lettura è stato fatto.
Così, dopo un EPOLLIN è necessario svuotare il buffer prima epoll_wait essere in grado di restituire una nuova EPOLLIN su nuovi dati.

Comunque sto sperimentando problemi con questo approccio, come sto vedendo eventi EPOLLIN duplicati per FDS incontaminati.
Questa è l'uscita strace, 0x200 è EPOLLRDHUP che non è ancora definita nei miei intestazioni glibc ma definita nel 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

Quindi, dopo aver aggiunto il numero 9 fd io ricevono 2 eventi EPOLLIN consecutivi prima di avere recving il descrittore di file, le syscall traccia mostra come faccio a cancellare il fd prima di leggere, ma dovrebbe avvenire solo una volta, uno per ogni evento.
Quindi, o io non sto leggendo la pagina di manuale correttamente o qualcosa sta lavorando qui.

È stato utile?

Soluzione

Credo che vi siete persi questa parte della pagina epoll man:

  

Dal momento che anche con il bordo-triggered   epoll più eventi possono essere generati   al ricevimento di molteplici pezzi di   i dati, il chiamante ha la possibilità di   specificare il flag EPOLLONESHOT, a   dire epoll per disabilitare il associato   descrittore di file dopo il ricevimento   un evento con epoll_wait(2). quando   viene specificato il flag EPOLLONESHOT,   è responsabilità del chiamante   riarmare il descrittore di file tramite   epoll_ctl(2) con EPOLL_CTL_MOD.

Questo è: hai due blocchi di dati che arrivano nella vostra coda di ricezione prima del primo read() accaduto, il che significa che avete ottenuto due eventi epoll. Sembra EPOLLONESHOT è quello che stai dopo, che atomicamente rimuovere il descrittore di file dal set sondaggio quando si verifica un evento su di essa (in modo che non sarà necessario fare il EPOLL_CTL_DEL).

Altri suggerimenti

Bordo grilletto significa semplicemente (a meno che non hai EPOLLONESHOT usato) che si otterrà 1 evento quando qualcosa entra nella (kernel) tampone.

Quindi, se si ottiene 1 evento EPOLLIN e non fare nulla su di esso, si otterrà un altro EPOLLIN la prossima volta che alcuni dati che arriva sul descrittore - se non arrivano nuovi dati, non si ottiene un evento, però, anche se non ha letto i dati come indicato dal primo evento.

Bene, per dirla succintamente, EPOLLONESHOT significa solo che se non si leggono i dati che si suppone di leggere, saranno scartati.

In genere, devi essere avvisato con un evento per gli stessi dati, se non li leggono. Con EPOLLONESHOT, tuttavia, non la lettura dei dati è perfettamente legale e saranno semplicemente ignorato. Quindi, saranno generati ulteriori eventi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top