No puedo agregar directamente a las respuestas excelentes dadas por David, templatetypedef, etc. - si desea evitar latencia de comunicaciones entre subprocesos y desperdicio de recursos, no haga intercomunicados con bucles sleep().
preventiva programación/despacho:
A nivel de la CPU, las interrupciones son la clave. El sistema operativo no hace nada hasta que ocurre una interrupción que hace que se ingrese su código. Tenga en cuenta que, en términos de OS, las interrupciones vienen en dos sabores: interrupciones de hardware "reales" que provocan la ejecución de controladores y "interrupciones de software". Estas son llamadas al sistema operativo de hilos que ya se están ejecutando y que pueden provocar el conjunto de subprocesos en ejecución. cambiar. Las pulsaciones de teclas, los movimientos del mouse, las tarjetas de red, los discos y las fallas de página generan interrupciones de hardware. Las funciones de espera y señal, y sleep(), pertenecen a esa segunda categoría. Cuando una interrupción de hardware hace que se ejecute un controlador, el controlador realiza la gestión de hardware para la que fue diseñado. Si el controlador necesita indicar al sistema operativo que es necesario ejecutar algún subproceso (quizás un búfer de disco esté ahora lleno y deba procesarse), el sistema operativo proporciona un mecanismo de entrada que el conductor puede llamar en lugar de ejecutar directamente una interrupción. volverse a sí mismo, (¡importante!).
Las interrupciones como las de los ejemplos anteriores pueden hacer que los subprocesos que estaban esperando estén listos para ejecutarse o que un subproceso en ejecución entre en estado de espera. Después de procesar el código de la interrupción, el sistema operativo aplica su/s algoritmo/s de planificación para decidir si el conjunto de hilos que se estaban ejecutando antes de la interrupción es el mismo que el que se debería ejecutar ahora. Si lo son, el sistema operativo simplemente interrumpe el retorno, de lo contrario, el sistema operativo debe adelantarse a uno o más de los hilos en ejecución. Si el sistema operativo necesita adelantarse a un hilo que se ejecuta en un núcleo de CPU que no es el que manejó la interrupción, tiene que obtener el control de ese núcleo de CPU. Lo hace por medio de una interrupción de hardware 'real': el controlador del interprocesador del sistema operativo establece una señal de hardware que interrumpe el núcleo que ejecuta el subproceso que se va a adelantar.
Cuando un subproceso que se va a sustituir entra en el código del sistema operativo, el sistema operativo puede guardar un contexto completo para el subproceso.Algunos de los registros ya se habrán guardado en la pila del hilo mediante la entrada de interrupción, por lo que al guardar el puntero de pila del hilo se 'guardarán' efectivamente todos esos registros, pero el sistema operativo normalmente necesitará hacer más, p.ej. las memorias caché pueden necesitar ser enjuagadas, el estado de la FPU puede necesitar ser guardado y, en el caso donde la nueva cadena a ser ejecutada pertenece a un proceso diferente al que se va a evitar, los registros de protección de administración de memoria deberán ser intercambiados . Por lo general, el sistema operativo cambia de la pila de hilos interrumpidos a una pila de SO privada lo antes posible para evitar infligir requisitos de pila de SO en cada pila de subprocesos.
Una vez que el o los contextos se guardan, el SO puede 'intercambiar' el/los contexto/s extendido/s por los nuevos hilos/s que se van a ejecutar. Ahora, el SO finalmente puede cargar el puntero de la pila para los nuevos subprocesos y realizar retornos de interrupción para ejecutar sus nuevos subprocesos listos.
El sistema operativo no hace nada en absoluto. Los subprocesos en ejecución se ejecutan hasta que se produce otra interrupción (dura o blanda).
puntos importantes:
1) El núcleo del sistema operativo debe ser considerado como una gran interrupción-controlador que puede decidir interrumpir retorno a un conjunto diferente de los hilos que las que interrumpidos.
2) El sistema operativo puede controlar y detener, si es necesario, cualquier hilo en cualquier proceso, sin importar en qué estado se encuentre o en qué núcleo se esté ejecutando.
3) La programación anticipada y el envío genera todos los problemas de sincronización que se publican en estos foros. La gran ventaja es la respuesta rápida en el nivel de hilo a las interrupciones duras. Sin esto, todas esas aplicaciones de alto rendimiento que ejecuta en su PC: transmisión de video, redes rápidas, etc., serían virtualmente imposibles.
4) El temporizador de sistema operativo es solo uno de un gran conjunto de interrupciones que pueden cambiar el conjunto de subprocesos en ejecución. 'Time-slicing', (ugh, odio ese término), entre los hilos listos solo ocurre cuando la computadora está sobrecargada, es decir. el conjunto de hilos listos es más grande que la cantidad de núcleos de CPU disponibles para ejecutarlos. Si algún texto que pretenda explicar la programación del sistema operativo menciona 'time-slicing' antes de 'interrupts', es probable que cause más confusión que explicación. La interrupción del temporizador es solo 'especial' ya que muchas llamadas al sistema tienen tiempos de espera para respaldar su función principal, (OK, para el modo reposo(), el tiempo de espera ES la función primaria :).
Solo me pregunto, ¿no es así como las funciones de espera funcionan internamente de todos modos? (Excluyendo obviamente la excepción) – Mehrdad
@ Mehrdad- Típicamente no. Por lo general, los hilos se colocan en una "cola de espera" y no reciben ningún tiempo de procesador. Cuando ocurre algún evento que los despierte, se colocan de nuevo en la cola de ejecución para que se programen. Esto significa que puede tener un millón de hilos inactivos sin pérdida de rendimiento si solo dos o tres hilos están activos al mismo tiempo. – templatetypedef
@templatetypedef: Entonces, ¿cómo exactamente el sistema operativo averiguar si los hilos se deben despertar en un segmento de tiempo determinado? ¿No debería verificar el estado del hilo en un bucle en cada segmento de tiempo? – Mehrdad