Articulo de referencia

proceso zombie

En los sistemas operativos Unix y similares , un proceso zombie o proceso difunto es un proceso que ha completado su ejecución (mediante la llamada al sistema ) pero que aún con...

En los sistemas operativos Unix y similares , un proceso zombie o proceso difunto es un proceso que ha completado su ejecución (mediante la llamada al sistema ) pero que aún conserva una entrada en la tabla de procesos : se trata de un proceso en estado de "terminado ". Esto ocurre con los procesos hijos , cuya entrada sigue siendo necesaria para que el proceso padre pueda leer su estado de salida . Una vez leído el estado de salida mediante la llamada al sistema , la entrada del proceso difunto se elimina de la tabla de procesos y se dice que ha sido "recogido". Un proceso hijo se convierte inicialmente en difunto, y solo entonces se elimina de la tabla de recursos. En condiciones normales de funcionamiento, los procesos difuntos son inmediatamente esperados por su padre y posteriormente recogidos por el sistema. Los procesos que permanecen difuntos durante mucho tiempo suelen ser un error y pueden provocar una fuga de recursos . Generalmente, el único recurso del kernel que ocupan es la entrada en la tabla de procesos, su ID de proceso. Sin embargo, los procesos difuntos también pueden mantener búferes abiertos, consumiendo memoria. Los procesos obsoletos pueden retener identificadores de descriptores de archivo, lo que impide que el sistema de archivos acceda al espacio destinado a dichos archivos. Este efecto se puede observar en la diferencia entre y . Mientras que puede mostrar una gran cantidad de espacio libre en disco, mostrará una partición llena. Si no se eliminan los procesos obsoletos, esto puede llenar la partición raíz y provocar un fallo del sistema.exitwaitdudfdudf

El término proceso zombi deriva de la definición común de zombi : una persona no muerta . En la metáfora del término, el proceso hijo ha " muerto " pero aún no ha sido " cosechado ". A diferencia de los procesos normales, el comando no tiene efecto sobre un proceso zombi. kill

Los procesos zombie no deben confundirse con los procesos huérfanos , un proceso que aún se está ejecutando, pero cuyo padre ha muerto. Cuando el padre muere, el proceso hijo huérfano es adoptado por init. Cuando los procesos huérfanos mueren, no permanecen como procesos zombie; en cambio, son waitcontinuados por init.

Descripción general

Cuando un proceso finaliza mediante exit, toda la memoria y los recursos asociados se liberan para que otros procesos puedan utilizarlos. Sin embargo, la entrada del proceso en la tabla de procesos permanece. El proceso padre puede leer el estado de salida del hijo ejecutando la waitllamada al sistema , tras lo cual se elimina el proceso zombie. La waitllamada puede ejecutarse en código secuencial, pero comúnmente se ejecuta en un manejador de la señal SIGCHLD , que el proceso padre recibe cuando un hijo ha finalizado.

Después de que se elimina el zombie, su identificador de proceso (PID) y su entrada en la tabla de procesos pueden reutilizarse. Sin embargo, si un padre no llama a wait, el zombie permanecerá en la tabla de procesos, causando una fuga de recursos . En algunas situaciones esto puede ser deseable: el proceso padre desea seguir manteniendo este recurso; por ejemplo, si el padre crea otro proceso hijo, se asegura de que no se le asigne el mismo PID. En sistemas modernos tipo UNIX (que cumplen con la especificación SUSv3 a este respecto), se aplica el siguiente caso especial: si el padre ignora explícitamente SIGCHLD estableciendo su manejador en SIG_IGN(en lugar de simplemente ignorar la señal por defecto) o tiene la SA_NOCLDWAITbandera establecida, toda la información de estado de salida del hijo se descartará y no quedarán procesos zombie. [ 1 ]

Los procesos zombie se pueden identificar en la salida del pscomando Unix por la presencia de un " Z" en la columna "STAT". [ 2 ] Los procesos zombie que existen durante más de un período corto de tiempo generalmente indican un error en el programa padre, o simplemente una decisión inusual de no cosechar los hijos (ver ejemplo). Si el programa padre ya no se está ejecutando, los procesos zombie generalmente indican un error en el sistema operativo. Al igual que con otras fugas de recursos, la presencia de algunos procesos zombie no es preocupante en sí misma, pero puede indicar un problema que se agravaría bajo cargas más pesadas. Dado que no hay memoria asignada a los procesos zombie (el único uso de memoria del sistema es para la entrada de la tabla de procesos en sí), la principal preocupación con muchos procesos zombie no es quedarse sin memoria , sino quedarse sin entradas de la tabla de procesos, concretamente números de ID de proceso. Sin embargo, los procesos zombie pueden mantener abiertos búferes que están asociados con descriptores de archivo y, por lo tanto, hacer que el proceso zombie consuma memoria. Los procesos zombie también pueden mantener un descriptor de archivo para un archivo que ha sido eliminado. Esto impide que el sistema de archivos recupere los i-nodos para el archivo eliminado. Por lo tanto, el comando para mostrar el uso del disco no contará los archivos eliminados cuyo espacio no se puede reutilizar debido a que el descriptor de archivo está siendo utilizado por un proceso zombie.

Para eliminar procesos zombie de un sistema, se puede enviar manualmente la señal SIGCHLD al proceso padre, utilizando el killcomando. Si el proceso padre aún se niega a eliminar el proceso zombie, y si no hay problema en terminar el proceso padre, el siguiente paso puede ser eliminar el proceso padre. Cuando un proceso pierde a su padre, initse convierte en su nuevo padre. initejecuta periódicamente la waitllamada al sistema para eliminar cualquier proceso zombie con initcomo padre.

Ejemplo

La espera síncrona de procesos secundarios específicos en un orden determinado puede provocar que los procesos zombie permanezcan activos durante más tiempo del mencionado "breve período de tiempo". Esto no implica necesariamente un error del programa.

#include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main ( void ) { pid_t pids [ 10 ]; int i ;for ( i = 9 ; i >= 0 ; -- i ) { pids [ i ] = fork (); if ( pids [ i ] == 0 ) { printf ( "Child%d \n " , i ); sleep ( i + 1 ); _exit ( 0 ); } }for ( i = 9 ; i >= 0 ; -- i ) { printf ( "padre%d \n " , i ); waitpid ( pids [ i ], NULL , 0 ); }devolver 0 ; }

Producción

padre9 Niño3 Niño4 Niño2 Niño 5 Niño1 Niño6 Niño0 Niño7 Niño8 Niño9 // hay una pausa aquí padre8 padre7 padre6 padre5 padre4 padre3 padre2 padre1 padre0 

Explicación

En el primer bucle, el proceso original (padre) crea 10 copias de sí mismo. Cada uno de estos procesos hijos (detectado porque fork() devuelve cero) imprime un mensaje, se suspende y finaliza. Todos los hijos se crean prácticamente al mismo tiempo (ya que el padre realiza muy poca actividad en el bucle), por lo que el momento en que cada uno se ejecuta por primera vez es algo aleatorio; de ahí el orden desordenado de sus mensajes.

Durante el bucle, se crea un array con los identificadores de los procesos hijos. Existe una copia del array ` pids[]` en los 11 procesos, pero solo en el proceso padre está completo; a la copia de cada hijo le faltarán los PID de los procesos hijos con números más bajos y tendrá cero como su propio PID. (Aunque esto no tiene mayor importancia, ya que solo el proceso padre utiliza este array).

El segundo bucle se ejecuta únicamente en el proceso padre (ya que todos los hijos han finalizado antes de este punto) y espera a que cada hijo termine. Espera al hijo que durmió 10 segundos primero; todos los demás ya han finalizado, por lo que todos los mensajes (excepto el primero) aparecen en rápida sucesión. No hay posibilidad de un orden aleatorio aquí, ya que está controlado por un bucle en un solo proceso. El primer mensaje del padre apareció antes que cualquiera de los mensajes de los hijos ; el padre pudo continuar en el segundo bucle antes de que cualquiera de los procesos hijos pudiera comenzar. Esto, de nuevo, es simplemente el comportamiento aleatorio del planificador de procesos: el mensaje "padre9" podría haber aparecido en cualquier punto de la secuencia antes de "padre8".

Child0 a Child8 permanecen en este estado durante uno o más segundos, entre el momento en que finalizan su ejecución y el momento en que el proceso padre ejecuta waitpid() sobre ellos. El proceso padre ya estaba esperando a Child9 antes de finalizar su ejecución, por lo que ese proceso prácticamente no permaneció como zombie. [ 3 ]

Véase también

Referencias

  1. "wait(2) Man Page" . Manual del programador de Linux .
  2. "Zombies(5) - UNIX System V (Conceptos)" . El detector de colisiones en Fermilab .
  3. "Linux - ¿Alguien puede explicar cómo funciona esto? fork(), sleep()" .
  • "Páginas man de UNIX  : ps()" . Ayuda de UNIX para usuarios . Archivado del original el 8 de marzo de 2013.
  • Proceso zombie, publicación de Usenet
  • Pregunta frecuente 3.13 de UNIX: ¿Cómo puedo eliminar los procesos zombie que persisten?