A veces, cada vez que escribo un programa en Linux y falla debido a algún tipo de error, se convertirá en un proceso ininterrumpido y continuará ejecutándose para siempre hasta que reinicie mi computadora (incluso si me desconecto). Mis preguntas son:
- ¿Qué hace que un proceso se vuelva ininterrumpible?
- ¿Cómo evito que eso suceda?
- Esta es probablemente una pregunta tonta, pero ¿hay alguna forma de interrumpirla sin reiniciar mi computadora?
linux
scheduling
preemption
Jason Baker
fuente
fuente
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_UNINTERUPTIBRespuestas:
Un proceso ininterrumpible es un proceso que se encuentra en una llamada del sistema (función del núcleo) que no puede ser interrumpido por una señal.
Para comprender lo que eso significa, debe comprender el concepto de una llamada de sistema interrumpible. El ejemplo clásico es
read()
. Esta es una llamada al sistema que puede llevar mucho tiempo (segundos), ya que potencialmente puede implicar girar un disco duro o mover cabezas. Durante la mayor parte de este tiempo, el proceso estará inactivo, bloqueando el hardware.Mientras el proceso está suspendido en la llamada del sistema, puede recibir una señal asincrónica de Unix (por ejemplo, SIGTERM), luego sucede lo siguiente:
Al regresar temprano de la llamada del sistema, el código de espacio del usuario puede alterar inmediatamente su comportamiento en respuesta a la señal. Por ejemplo, terminando limpiamente en reacción a SIGINT o SIGTERM.
Por otro lado, algunas llamadas al sistema no pueden interrumpirse de esta manera. Si el sistema llama a puestos de venta por alguna razón, el proceso puede permanecer indefinidamente en este estado indestructible.
LWN publicó un buen artículo que tocó este tema en julio.
Para responder la pregunta original:
Cómo evitar que esto suceda: averigua qué controlador te está causando problemas y deja de usarlo o conviértete en un hacker del kernel y arréglalo.
Cómo matar un proceso ininterrumpido sin reiniciar: de alguna manera hacer que la llamada al sistema finalice. Con frecuencia, la forma más efectiva de hacerlo sin presionar el interruptor de alimentación es tirar del cable de alimentación. También puede convertirse en un hacker del kernel y hacer que el controlador use TASK_KILLABLE, como se explica en el artículo LWN.
fuente
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
ySIGKILL
). 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).
fuente
Los procesos ininterrumpidos normalmente esperan E / S después de un error de página.
Considera esto:
El proceso / tarea no se puede interrumpir en este estado, porque no puede manejar ninguna señal; si lo hiciera, ocurriría otra falla de página y volvería a estar donde estaba.
Cuando digo "proceso", realmente me refiero a "tarea", que en Linux (2.6) se traduce aproximadamente como "hilo" que puede tener o no una entrada individual de "grupo de hilos" en / proc
En algunos casos, puede estar esperando mucho tiempo. Un ejemplo típico de esto sería donde el archivo ejecutable o mmap'd está en un sistema de archivos de red donde el servidor ha fallado. Si la E / S finalmente tiene éxito, la tarea continuará. Si finalmente falla, la tarea generalmente obtendrá un SIGBUS o algo así.
fuente
A su tercera pregunta: creo que puede matar los procesos ininterrumpidos mediante la ejecución
sudo kill -HUP 1
. Reiniciará init sin finalizar los procesos en ejecución y después de ejecutarlo, mis procesos ininterrumpidos desaparecieron.fuente
Si está hablando de un proceso "zombie" (que se designa como "zombie" en la salida ps), este es un registro inofensivo en la lista de procesos que espera que alguien recopile su código de retorno y podría ignorarse con seguridad.
¿Podría por favor describir qué y "proceso ininterrumpido" es para usted? ¿Sobrevive al "kill -9" y felizmente avanza? Si ese es el caso, entonces está atascado en alguna llamada al sistema, que está atascado en algún controlador, y usted está atascado con este proceso hasta que se reinicie (y a veces es mejor reiniciarlo pronto) o la descarga del controlador relevante (lo que es poco probable que suceda) . Podrías intentar usar "strace" para descubrir dónde está atascado tu proceso y evitarlo en el futuro.
fuente