Estoy tratando de entender qué es un ciclo de eventos. A menudo, la explicación es que en un bucle de eventos, usted hace algo hasta que se le notifique que ha ocurrido un evento. Luego manejas el evento y continúas haciendo lo que estabas haciendo antes.
Para mapear la definición anterior con un ejemplo. Tengo un servidor que 'escucha' en un bucle de eventos, y cuando se detecta una conexión de socket, los datos se leen y se muestran, después de lo cual el servidor se reanuda / comienza a escuchar como lo hizo antes.
Sin embargo, este evento que está ocurriendo y que nos notifiquen 'así como así' es demasiado para mí. Puede decir: "No es" así ", debe registrar un oyente de eventos". Pero, ¿qué es un detector de eventos sino una función que por alguna razón no regresa? ¿Está en su propio ciclo, esperando ser notificado cuando ocurre un evento? ¿El oyente de eventos también debe registrar un oyente de eventos? Donde termina
Los eventos son una buena abstracción para trabajar, sin embargo, solo una abstracción. Creo que al final, las encuestas son inevitables. Quizás no lo estamos haciendo en nuestro código, pero los niveles inferiores (la implementación del lenguaje de programación o el sistema operativo) lo están haciendo por nosotros.
Básicamente se reduce al siguiente pseudocódigo que se está ejecutando en un lugar lo suficientemente bajo como para no generar una espera ocupada:
while(True):
do stuff
check if event has happened (poll)
do other stuff
Esta es mi comprensión de toda la idea, y me gustaría saber si esto es correcto. Estoy abierto a aceptar que toda la idea es fundamentalmente errónea, en cuyo caso me gustaría la explicación correcta.
fuente
EventSource
haciendo si no sondea la entrada del teclado?Respuestas:
La mayoría de los bucles de eventos se suspenderán si no hay eventos listos, lo que significa que el sistema operativo no dará tiempo de ejecución a la tarea hasta que ocurra un evento.
Digamos que el evento es una tecla que se está presionando. Puede preguntar si hay un bucle en alguna parte del sistema operativo que comprueba si se presionan teclas. La respuesta es no. Las teclas que se presionan generan una interrupción , que el hardware maneja de forma asíncrona. Del mismo modo para temporizadores, movimientos del mouse, un paquete que llega, etc.
De hecho, para la mayoría de los sistemas operativos, el sondeo de eventos es la abstracción. El hardware y el sistema operativo manejan los eventos de forma asíncrona y los colocan en una cola que las aplicaciones pueden sondear. Solo se ven verdaderas encuestas a nivel de hardware en sistemas integrados, e incluso allí no siempre.
fuente
Most event loops will block
. ¿Cómo encaja esto en "el paradigma del bucle de eventos, en lugar de usar hilos, usa llamadas asincrónicas sin bloqueo"?Pienso en un oyente de eventos no como una función que ejecuta su propio bucle, sino como una carrera de relevos con el primer corredor esperando el arma inicial. Una razón importante para usar eventos en lugar de sondeo es que son más eficientes con los ciclos de la CPU. ¿Por qué? Míralo desde el hardware hacia arriba (en lugar del código fuente hacia abajo).
Considere un servidor web. Cuando su servidor llama
listen()
y bloquea, su código está tomando su lugar como un corredor de retransmisión. Cuando llega el primer paquete de una nueva conexión, la tarjeta de red comienza la carrera interrumpiendo el sistema operativo. El sistema operativo ejecuta una rutina de servicio de interrupción (ISR) que toma el paquete. El ISR pasa el testigo a una rutina de nivel superior que establece la conexión. Una vez que la conexión está activa, esa rutina pasa el testigolisten()
a su código. En ese momento, puede hacer lo que quiera con la conexión. Por lo que sabemos, entre carreras, cada corredor de relevos podría ir al pub. Una de las ventajas de la abstracción de eventos es que su código no tiene que saberlo ni preocuparse.Algunos sistemas operativos incluyen un código de manejo de eventos que ejecuta su parte de la carrera, se quita el testigo y luego regresa a su punto de partida para esperar a que comience la próxima carrera. En ese sentido, el manejo de eventos es un sondeo optimizado en muchos bucles concurrentes. Sin embargo, siempre hay un disparador externo que inicia el proceso. El detector de eventos no es una función que no regresa, sino una función que está esperando ese disparador externo antes de que se ejecute. Más bien que:
Pienso en esto como:
y entre el
signal
y la próxima vez que se ejecuta el controlador, conceptualmente no hay código en ejecución o bucle.fuente
forever: { select(); do stuff; }
entonces volverá a ingresar a la carrera cada vez que pase por el bucle. Ya sea que lo haga repetidamente desde un solo subproceso o en paralelo en subprocesos o procesadores separados, creo que cada evento es su propia raza. Por ejemplo, un navegador web es un programa multiproceso con múltiples bucles de eventos en hilos separados, al menos uno para la interfaz de usuario y uno para cada página que está descargando. La pregunta que hago al codificar es "¿cómo puedo procesar eventos lo suficientemente rápido?" A veces la respuesta es un bucle, a veces hilos, a menudo una combinación.No. No es un "sondeo optimizado". Un bucle de eventos utiliza E / S controladas por interrupción en lugar de sondeo.
Los bucles Mientras, Hasta, Para, etc. son bucles de sondeo.
"Encuesta" es el proceso de verificar repetidamente algo. Dado que el código del bucle se ejecuta continuamente, y debido a que es un bucle pequeño y "ajustado", hay poco tiempo para que el procesador cambie las tareas y haga cualquier otra cosa. Casi todos los "bloqueos", "bloqueos", "bloqueos" o como quiera llamarlo cuando la computadora deja de responder, son la manifestación de que el código está atascado en un bucle de sondeo involuntario. La instrumentación mostrará el uso del 100% de la CPU.
Los bucles de eventos controlados por interrupciones son mucho más eficientes que los bucles de sondeo. El sondeo es un uso extremadamente derrochador de los ciclos de CPU, por lo que se hace todo lo posible para eliminarlo o minimizarlo.
Sin embargo, para optimizar la calidad del código, la mayoría de los idiomas intentan utilizar el paradigma del bucle de sondeo lo más cerca posible para los comandos de entrega de eventos, ya que sirven para propósitos funcionalmente similares dentro de un programa. Por lo tanto, dado que el sondeo es la forma más familiar de esperar una pulsación de tecla o algo así, es fácil para los inexpertos usarlo y terminar con un programa que puede funcionar bien por sí mismo, pero nada más funciona mientras se está ejecutando. Se ha "apoderado" de la máquina.
Como se explicó en otras respuestas, en la entrega de eventos impulsados por interrupciones, esencialmente se establece un "indicador" dentro de la CPU y el proceso se "suspende" (no se permite que se ejecute) hasta que otro indicador modifique ese indicador (como el teclado controlador que lo cambia cuando el usuario ha presionado una tecla). Si el indicador es una condición de hardware real, como una línea que se "tira hacia arriba", se llama "interrupción" o "interrupción de hardware". La mayoría, sin embargo, se implementan solo como una dirección de memoria en la CPU o en la memoria principal (RAM) y se denominan "semáforos".
Los semáforos se pueden cambiar bajo el control del software y, por lo tanto, pueden proporcionar un mecanismo de señalización muy rápido y simple entre los procesos del software.
Sin embargo, las interrupciones solo se pueden cambiar por hardware. El uso más ubicuo de las interrupciones es el que se activa a intervalos regulares por el chip de reloj interno. Uno de los innumerables tipos de acciones de software activadas por interrupciones de reloj es el cambio de semáforos.
He dejado mucho de lado pero tuve que parar en alguna parte. Por favor pregunte si necesita más detalles.
fuente
Por lo general, la respuesta es el hardware, el sistema operativo y los subprocesos en segundo plano que no controlas conspiran para que parezca sin esfuerzo. La tarjeta de red recibe algunos datos, genera una interrupción para informar a la CPU. El controlador de interrupciones del sistema operativo lo maneja. Luego, el sistema operativo despierta un subproceso de fondo que no controla (que se creó al registrarse para el evento y que ha estado inactivo desde que se registró para el evento) como parte del manejo del evento y ejecuta su controlador de eventos.
fuente
Voy a ir en contra de todas las otras respuestas que veo hasta ahora y decir "sí" . Creo que las otras respuestas están complicando demasiado las cosas. Desde un punto de vista conceptual, todos los bucles de eventos son esencialmente:
Si está tratando de comprender los bucles de eventos por primera vez, pensar en ellos como un bucle simple no hará daño. Algunos marcos subyacentes están esperando que el SO entregue un evento, luego lo enruta a uno o más controladores, luego espera el próximo evento, y así sucesivamente. Eso es realmente todo lo que hay que hacer desde una perspectiva de software de aplicación.
fuente
No todos los desencadenantes de eventos se manejan en bucles. La forma en que a menudo escribo mis propios motores de eventos sería así:
Tenga en cuenta que aunque Memo 1 está en un bucle, el bucle es para notificar a cada oyente. El desencadenador de evento en sí no está necesariamente en un bucle.
En teoría, los eventos clave a nivel del sistema operativo pueden usar la misma técnica (aunque creo que a menudo hacen encuestas, solo estoy especulando aquí), siempre que el sistema operativo exponga algún tipo de
registerListener
API.fuente