Cuando un FD se convierte en lectura o escritura listo, es posible que no necesariamente desee leer (o escribir) todos los datos de inmediato.
epoll activado por nivel seguirá molestándolo mientras el FD permanezca listo, mientras que el disparo por flanco no lo molestará nuevamente hasta la próxima vez que obtenga un EAGAIN
(por lo que es más complicado codificar, pero puede ser más eficiente dependiendo de lo que necesite hacer).
Supongamos que está escribiendo de un recurso a un FD. Si registra su interés para que ese FD se convierta en listo para escritura como desencadenado por nivel, recibirá notificación constante de que el FD todavía está listo para la escritura. Si el recurso aún no está disponible, es un desperdicio de un despertar, porque de todos modos no puedes escribir más.
Si fuera a agregarlo como activado por flanco en su lugar, recibiría la notificación de que el FD estaba listo para escritura una vez, luego, cuando el otro recurso esté listo, escriba todo lo que pueda. Luego, si write(2)
devuelve EAGAIN
, deja de escribir y espera la siguiente notificación.
Lo mismo aplica para la lectura, ya que es posible que no desee extraer todos los datos en el espacio del usuario antes de que esté listo para hacer lo que quiera con él (tener que almacenarlo, etc.). Con epoll desencadenado por flancos, se le informa cuando está listo para leer, y luego puede recordar eso y hacer la lectura real "como y cuando".
¿Este comportamiento activado por el borde es seguro contra las condiciones de carrera, p. si los datos están disponibles después de 'leer 'falla con' EAGAIN' pero antes de llamar a 'epoll'? –
Sure. 'epoll' simplemente regresa inmediatamente si el FD ya está listo y aún no se te ha notificado. –
ET también es particularmente agradable con un servidor multiproceso en una máquina multinúcleo. Puede ejecutar un hilo por núcleo y hacer que todos ellos llamen epoll_wait en la misma dfpe. Cuando los datos entran en un fd, se despierta exactamente un hilo para manejarlo. –