Cuando un proceso está en modo de usuario, puede interrumpirse en cualquier momento (cambiar al modo kernel). Cuando el kernel vuelve al modo de usuario, comprueba si hay señales pendientes (incluidas las que se utilizan para matar el proceso, como SIGTERM
y SIGKILL
). Esto significa que un proceso solo se puede eliminar al volver al modo de usuario.
La razón por la que un proceso no se puede eliminar en modo kernel es que podría corromper las estructuras del kernel utilizadas por todos los demás procesos en la misma máquina (de la misma manera, matar un hilo puede dañar las estructuras de datos utilizadas por otros hilos en el mismo proceso) .
Cuando el kernel necesita hacer algo que podría llevar mucho tiempo (esperar en una tubería escrita por otro proceso o esperar a que el hardware haga algo, por ejemplo), duerme al marcarse como inactivo y llamar al programador para cambiar a otro proceso (si no hay un proceso que no duerma, cambia a un proceso "ficticio" que le dice a la CPU que disminuya la velocidad un poco y se sienta en un bucle: el bucle inactivo).
Si se envía una señal a un proceso de suspensión, debe despertarse antes de que regrese al espacio del usuario y así procesar la señal pendiente. Aquí tenemos la diferencia entre los dos tipos principales de sueño:
TASK_INTERRUPTIBLE
, el sueño interrumpible. Si una tarea está marcada con esta bandera, está durmiendo, pero puede ser despertada por señales. Esto significa que el código que marcó la tarea como en espera está esperando una posible señal, y después de que se active, la verificará y regresará de la llamada al sistema. Una vez que se maneja la señal, la llamada del sistema puede reiniciarse automáticamente (y no entraré en detalles sobre cómo funciona).
TASK_UNINTERRUPTIBLE
, el sueño ininterrumpido. Si una tarea está marcada con este indicador, no espera ser despertada por nada más que lo que esté esperando, ya sea porque no puede reiniciarse fácilmente o porque los programas esperan que la llamada del sistema sea atómica. Esto también se puede usar para dormir que se sabe que son muy cortos.
TASK_KILLABLE
(mencionado en el artículo LWN vinculado por la respuesta de ddaa) es una nueva variante.
Esto responde a tu primera pregunta. En cuanto a su segunda pregunta: no puede evitar dormir ininterrumpidamente, son algo normal (sucede, por ejemplo, cada vez que un proceso lee / escribe desde / en el disco); sin embargo, deberían durar solo una fracción de segundo. Si duran mucho más, generalmente significa un problema de hardware (o un problema de controlador de dispositivo, que tiene el mismo aspecto para el núcleo), donde el controlador de dispositivo está esperando que el hardware haga algo que nunca sucederá. También puede significar que está utilizando NFS y que el servidor NFS está inactivo (está esperando que el servidor se recupere; también puede usar la opción "intr" para evitar el problema).
Finalmente, la razón por la que no puede recuperarse es la misma razón por la que el kernel espera hasta que regrese al modo de usuario para entregar una señal o matar el proceso: podría corromper las estructuras de datos del kernel (el código que espera un sueño interrumpible puede recibir un error que le indica para volver al espacio del usuario, donde se puede eliminar el proceso; el código que espera en una suspensión ininterrumpida no espera ningún error).
TASK_UNINTERUPTIBLE
estado cada vez que el sistema no está en un estado inactivo, recolectando datos de manera forzada, esperando transmitir una vez que el superusuario sale? Esta sería una mina de oro para que los hackers recuperen información, regresen al estado zombie y transmitan información a través de la red en inactivo. Algunos pueden argumentar que esta es una forma de crear un poderBlackdoor
para los poderes fácticos, para ingresar y salir de cualquier sistema como se desee. Creo firmemente que esta escapatoria puede ser sellada para siempre, eliminando el `TASK_UNINTERUPTIB