Pregunta

La página de manual epoll dice que un fd registrado en EPOLLET (borde activa) no debe notificar a EPOLLIN dos veces si no se ha hecho lectura.
Así que después de un EPOLLIN que necesita para vaciar el búfer antes de epoll_wait ser capaz de devolver una nueva EPOLLIN en nuevos datos.

Sin embargo, yo estoy experimentando problemas con este enfoque, ya que estoy viendo eventos duplicados para EPOLLIN FDS vírgenes.
Esta es la salida de strace, 0x200 es EPOLLRDHUP que no está definido todavía en mis cabeceras glibc sino que se define en el 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

Así que, después de añadir fd número 9 que reciben los 2 eventos consecutivos antes de tener EPOLLIN recving el descriptor de archivo, las llamadas al sistema de rastreo muestra la forma en que hago borrar el fd antes de leer pero sólo debería ocurrir una vez, uno por cada evento.
Así que, o yo no estoy leyendo la página de manual correctamente o algo está trabajando aquí.

¿Fue útil?

Solución

Creo que se ha perdido esta parte de la página del manual epoll:

  

Dado que incluso con el disparado por flanco   epoll múltiples eventos pueden ser generados   tras la recepción de múltiples trozos de   los datos, la persona que llama tiene la opción de   especificar el indicador EPOLLONESHOT, a   decir epoll para desactivar el asociado   descriptor de archivo después de la recepción de   un evento con epoll_wait(2). Cuando   se especifica el indicador EPOLLONESHOT,   es responsabilidad de la persona que llama   rearmar el descriptor de archivo usando   epoll_ctl(2) con EPOLL_CTL_MOD.

Esto es: tienes dos trozos de datos que llegan en su cola de recepción antes de que ocurriera la primera read(), lo que significa que tienes dos eventos epoll. Parece que EPOLLONESHOT es lo que está buscando, lo que eliminará atómicamente el descriptor de archivo del conjunto encuesta cuando ocurre un evento en el mismo (por lo que no tendrá que hacer el EPOLL_CTL_DEL).

Otros consejos

disparo por flanco simplemente significa (a menos que haya usado EPOLLONESHOT) que obtendrá 1 evento cuando algo entra en el (kernel) de amortiguación.

Por lo tanto, si se obtiene 1 evento EPOLLIN y no hacer nada al respecto, obtendrá otro EPOLLIN la próxima vez que algún datos llegan en ese descriptor - si no se obtiene nuevos datos, que no obtendrá un evento sin embargo, incluso si no leyó ningún dato según lo indicado por el primer evento.

Bueno, para decirlo de manera sucinta, EPOLLONESHOT sólo significa que si usted no lee los datos que se supone que leer, que serán descartados.

Normalmente, había una notificación con un evento para los mismos datos si no los lee. Con EPOLLONESHOT, sin embargo, no la lectura de los datos es perfectamente legal y que será simplemente ignorada. Por lo tanto, no se generarán más eventos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top