Mirando la fuente de strace
, 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 en él, descubrí que, aunque ese indicador no está cubierto man clone
, el núcleo lo usa realmente 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 (ver pregunta más abajo) tales procesos "en ejecución" (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 núcleo asigna un proceso real para ejecutar o asignar el proceso inactivo una vez más (si la CPU no se está utilizando). Sin embargo, eso 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 tendrá una CPU mientras no se realice el trabajo en el espacio del usuario?)
¿Es el proceso inactivo realmente solo un flujo infinito de operaciones NOP? (o un bucle que hace lo mismo).
¿El uso de la CPU (por ejemplo
uptime
) simplemente se calcula 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 buena parte de esta pregunta se deba al hecho de que no entiendo completamente cómo funciona una CPU. es decir, entiendo el ensamblaje, los plazos y las interrupciones, pero no sé cómo, por ejemplo, una CPU puede usar más o menos energía dependiendo de lo que esté ejecutando. Estaría agradecido si alguien me puede iluminar sobre eso también.
fuente
Respuestas:
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 otro proceso para ejecutarse en esa CPU, se programa la tarea inactiva. El tiempo dedicado a las tareas inactivas aparece como tiempo "inactivo" en herramientas como
top
. (El tiempo de actividad se calcula de manera diferente).Parece que Unix siempre ha tenido un ciclo inactivo de algún tipo (pero no necesariamente una tarea inactiva real, vea la respuesta de Gilles ), e incluso en V1 usó una
WAIT
instrucción que detuvo el procesador hasta que se produjo una interrupción (significaba "espere interrumpir"). Algunos otros sistemas operativos utilizan bucles ocupados, DOS, OS / 2 y las primeras versiones de Windows en particular. Desde hace bastante tiempo, las CPU han utilizado este tipo de instrucciones de "espera" para reducir su consumo de energía y producción de calor. Puede ver varias implementaciones de tareas inactivas, por ejemplo,arch/x86/kernel/process.c
en el kernel de Linux: la básica solo llamaHLT
, que detiene el procesador hasta que se produce una interrupción (y habilita el modo de ahorro de energía C1), las otras implementaciones manejan varios errores o ineficiencias ( por ejemplo, el uso enMWAIT
lugar deHLT
en algunas CPU).Todo esto está completamente separado de los estados inactivos en los procesos, cuando están esperando un evento (E / S, etc.).
fuente
play_dead()
es un nombre mnemotécnico muy bueno para ejecutar HALT. ¿No habría riesgo de enviar HALT a cada CPU y, en consecuencia, colgarse? (es decir, llegar a esa situación, HALT cada CPU, ¿sería un error en el núcleo correcto?)En el diseño del libro de texto de un planificador de procesos, si el planificador no tiene ningún proceso para programar (es decir, si todos los procesos están bloqueados, esperando la entrada), entonces el planificador espera una interrupción del procesador. La interrupción puede indicar la 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 planificador de Linux no tiene un código especial para un caso de nada que hacer. En cambio, codifica el caso de nada que hacer como un proceso especial, el proceso inactivo. El proceso inactivo solo se programa cuando ningún otro proceso es programable (tiene una prioridad infinitamente baja). El proceso inactivo es, de hecho, parte del núcleo: es un subproceso del núcleo, es decir, un subproceso que ejecuta código en el núcleo, en lugar de código en un proceso. (Más precisamente, hay 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 solo un bucle ocupado:
El procesador sigue ejecutando una instrucción de bifurcación para siempre, 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 hay nada mejor, y la mayoría de los procesadores tienen algo mejor. En lugar de gastar energía haciendo nada más que calentar la habitación, idealmente, el procesador debe estar 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 pequeña parte que permanezca encendida, el controlador de interrupción. Cuando un periférico dispara una interrupción, el controlador de interrupción enviará una señal de activación al procesador (parte del) principal.
En la práctica, las CPU modernas como Intel / AMD y ARM tienen muchas configuraciones complejas 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 baja potencia dependiendo 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 frecuencia de reloj del procesador cuando descubre que los procesos no consumen mucho tiempo de CPU.
fuente
HLT
podría apagar las variantes SL del 386 y 486, antes de que saliera el DX4 (el artículo de Wikipedia es incorrecto).No, una tarea inactiva no desperdicia los ciclos de la CPU. El planificador simplemente no selecciona un proceso inactivo para su ejecución. Un proceso inactivo está esperando que ocurra algún evento para que pueda continuar. Por ejemplo, puede estar esperando la entrada en una
read()
llamada al sistema.Por cierto, el núcleo 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 hilo del kernel), por lo que no es correcto decir "y una CPU estará en el kernel mientras no se realice el trabajo en el espacio del usuario".
fuente