
Mirando la fuente destrace
Encontré el uso de la bandera de clonación CLONE_IDLETASK
que se describe allí como:
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
Después de profundizar más, descubrí que, aunque ese indicador no está cubierto, en man clone
realidad el kernel lo usa durante el proceso de arranque para crear procesos inactivos (todos los cuales deberían tener PID 0) para cada CPU en la máquina. es decir, una máquina con 8 CPU tendrá al menos 7 (consulte la pregunta a continuación) de estos procesos "ejecutándose" (tenga en cuenta las comillas).
Ahora, esto me lleva a un par de preguntas sobre qué hace realmente ese proceso "inactivo". Mi suposición es que ejecuta la operación NOP continuamente hasta que finaliza su período de tiempo y el kernel asigna un proceso real para ejecutar o asigna el proceso inactivo una vez más (si no se está utilizando la CPU). Sin embargo, esa es una suposición completa. Entonces:
En una máquina con, digamos, 8 CPU, ¿se crearán 7 procesos inactivos? (¿Y el núcleo mismo mantendrá una CPU mientras no se realice trabajo en el espacio de usuario?)
¿El proceso inactivo es realmente solo un flujo infinito de operaciones NOP? (o un bucle que hace lo mismo).
¿El uso de la CPU (digamos
uptime
) se calcula simplemente por cuánto tiempo estuvo el proceso inactivo en la CPU y cuánto tiempo no estuvo allí durante un cierto período de tiempo?
PD: Es probable que gran parte de esta pregunta se deba al hecho de que no entiendo completamente cómo funciona una CPU. es decir, entiendo el montaje, los tiempos y las interrupciones pero no sé cómo, por ejemplo, una CPU puede consumir más o menos energía dependiendo de lo que esté ejecutando. Agradecería que alguien pudiera iluminarme sobre eso también.
Respuesta1
La tarea inactiva se utiliza para la contabilidad de procesos y también para reducir el consumo de energía. En Linux, se crea una tarea inactiva para cada procesador y se bloquea en ese procesador; Siempre que no haya ningún otro proceso para ejecutar en esa CPU, se programa la tarea inactiva. El tiempo dedicado a tareas inactivas aparece como tiempo "inactivo" en herramientas como top
. (El tiempo de actividad se calcula de manera diferente).
Unix parece haber tenido siempre algún tipo de bucle inactivo (pero no necesariamente una tarea inactiva real, consulteLa respuesta de Gilles.), e incluso en V1usó una WAIT
instrucciónque detuvo el procesador hasta que ocurrió una interrupción (que significaba "esperar interrupción"). Algunos otros sistemas operativos usaban bucles ocupados, DOS,OS/2y las primeras versiones de Windows en particular. Desde hace bastante tiempo, las CPU utilizan este tipo de instrucción de “espera” para reducir su consumo de energía y producción de calor. Puede ver varias implementaciones de tareas inactivas, por ejemplo, enarch/x86/kernel/process.c
en el kernel de Linux: el básico simplemente llamaHLT
, que detiene el procesador hasta que ocurre una interrupción (y habilita el modo de ahorro de energía C1), las otras implementaciones manejan varios errores o ineficiencias (p.ejusando MWAIT
en lugar de HLT
en algunas CPU).
Todo esto es completamente independiente de los estados inactivos en los procesos, cuando están esperando un evento (E/S, etc.).
Respuesta2
En el diseño de libro de texto de un programador de procesos, si el programador no tiene ningún proceso que programar (es decir, si todos los procesos están bloqueados, esperando una entrada), entonces el programador espera una interrupción del procesador. La interrupción puede indicar una entrada de un periférico (acción del usuario, paquete de red, lectura completa de un disco, etc.) o puede ser una interrupción del temporizador que activa un temporizador en un proceso.
El programador de Linux no tiene un código especial para casos en los que no hay nada que hacer. En cambio, codifica el caso de nada que hacer como un proceso especial, el proceso inactivo. El proceso inactivo sólo se programa cuando no se puede programar ningún otro proceso (de hecho, tiene una prioridad infinitamente baja). El proceso inactivo es, de hecho, parte del núcleo: es un hilo del núcleo, es decir, un hilo que ejecuta código en el núcleo, en lugar de código en un proceso. (Más precisamente, existe un subproceso de este tipo para cada CPU). Cuando se ejecuta el proceso inactivo, realiza la operación de espera de interrupción.
El funcionamiento de la espera de interrupción depende de las capacidades del procesador. Con el diseño de procesador más básico, eso es sólo un bucle ocupado.
nothing:
goto nothing
El procesador sigue ejecutando una instrucción de bifurcación para siempre, lo que no logra nada. La mayoría de los sistemas operativos modernos no hacen esto a menos que se ejecuten en un procesador donde no haya nada mejor, y la mayoría de los procesadores tienen algo mejor. En lugar de gastar energía sin hacer nada más que calentar la habitación, lo ideal es que el procesador esté apagado. Entonces el kernel ejecuta un código que le indica al procesador que se apague solo, o al menos que apague la mayor parte del procesador. Debe haber al menos una pieza pequeña que permanezca encendida: el controlador de interrupciones. Cuando un periférico activa una interrupción, el controlador de interrupciones enviará una señal de activación a la (parte) principal del procesador.
En la práctica, las CPU modernas como Intel/AMD y ARM tienen muchas y complejas configuraciones de administración de energía. El sistema operativo puede estimar cuánto tiempo permanecerá el procesador en modo inactivo y elegirá diferentes modos de bajo consumo en función de esto. Los modos ofrecen diferentes compromisos entre el uso de energía mientras está inactivo y el tiempo que lleva entrar y salir del modo inactivo. En algunos procesadores, el sistema operativo también puede reducir la velocidad del reloj del procesador cuando descubre que los procesos no consumen mucho tiempo de CPU.
Respuesta3
No, una tarea inactiva no desperdicia ciclos de CPU. El planificador simplemente no selecciona un proceso inactivo para su ejecución. Un proceso inactivo está esperando que ocurra algún evento para poder continuar. Por ejemplo, puede estar esperando una entrada en una read()
llamada al sistema.
Por cierto, el kernel no es un proceso separado. El código del kernel siempre se ejecuta en el contexto de un proceso (bueno, excepto en el caso especial de un subproceso del kernel), por lo que no es correcto decir "y el kernel mismo mantendrá una CPU mientras no se realice trabajo en el espacio de usuario".