En informática, un proceso padre es un proceso que ha creado uno o más procesos hijo .
Sistemas similares a Unix
En los sistemas operativos similares a Unix , todos los procesos excepto el proceso 0 (el intercambiador) se crean cuando otro proceso ejecuta la llamada al sistema fork () . El proceso que invocó la bifurcación es el proceso padre y el proceso recién creado es el proceso hijo . Cada proceso (excepto el proceso 0) tiene un proceso padre, pero puede tener muchos procesos hijo.
El kernel del sistema operativo identifica cada proceso por su identificador de proceso. El proceso 0 es un proceso especial que se crea cuando se inicia el sistema; después de bifurcar un proceso hijo (proceso 1), el proceso 0 se convierte en el proceso de intercambio (a veces también conocido como " tarea inactiva "). El proceso 1 , conocido como init , es el antepasado de todos los demás procesos del sistema. [1]
Linux
En el kernel de Linux , en el que hay una diferencia muy pequeña entre los procesos y los subprocesos POSIX , hay dos tipos de procesos padre, a saber, el padre real y el padre. El padre es el proceso que recibe la señal SIGCHLD en la terminación del hijo, mientras que el padre real es el hilo que realmente creó este proceso hijo en un entorno multiproceso. Para un proceso normal, estos dos valores son iguales, pero para un subproceso POSIX que actúa como un proceso, estos dos valores pueden ser diferentes. [2]
Procesos zombies
El sistema operativo mantiene una tabla que asocia cada proceso, mediante su identificador de proceso (generalmente denominado " pid ") a los datos necesarios para su funcionamiento. Durante la vida útil de un proceso, dichos datos pueden incluir segmentos de memoria designados para el proceso, los argumentos con los que se ha invocado, las variables de entorno , los contadores sobre el uso de recursos, la identificación de usuario, la identificación de grupo y el conjunto de grupos, y tal vez otros tipos de información.
Cuando un proceso termina su ejecución, ya sea llamando a exit (aunque sea implícitamente, ejecutando un comando de retorno desde la función principal ) o recibiendo una señal que hace que termine abruptamente, el sistema operativo libera la mayoría de los recursos y la información relacionada con ese proceso, pero aún conserva los datos sobre la utilización de recursos y el código de estado de terminación , porque un proceso padre podría estar interesado en saber si ese hijo se ejecutó correctamente (mediante el uso de funciones estándar para decodificar el código de estado de terminación) y la cantidad de recursos del sistema que consumido durante su ejecución.
De forma predeterminada, el sistema asume que el proceso padre está realmente interesado en dicha información en el momento de la terminación del niño y, por lo tanto, envía al padre la señal SIGCHLD para alertar que hay algunos datos sobre un niño que deben recopilarse. Dicha recopilación se realiza llamando a una función de la familia de espera (ya sea wait a sí misma o a uno de sus parientes, como waitpid , waitid o wait4 ). Tan pronto como se realiza esta recopilación, el sistema libera esos últimos bits de información sobre el proceso hijo y elimina su pid de la tabla de procesos. Sin embargo, si el proceso padre se demora en recopilar los datos del niño (o no lo hace en absoluto), el sistema no tiene otra opción que mantener los datos de terminación y pid del niño en la tabla de proceso de manera indefinida.
Dicho proceso terminado cuyos datos no se han recopilado se denomina proceso zombi , o simplemente zombi , en el lenguaje de UNIX. El nombre es una analogía humorística debido a que se considera que el proceso terminado como "ya no está vivo" o "muerto", dado que realmente ha dejado de funcionar, y un proceso muerto persistente todavía "encarnado" en los procesos del "mundo de los vivos": el proceso tabla, que por lo tanto es en realidad "no-muerto" o "zombi".
Los procesos zombis pueden plantear problemas en sistemas con recursos limitados o que tienen tablas de procesos de tamaño limitado, ya que la creación de procesos nuevos y activos podría evitarse por la falta de recursos que aún utilizan los zombis de larga duración.
Por lo tanto, es una buena práctica de programación en cualquier programa que pueda generar procesos secundarios para tener código para evitar la formación de zombis duraderos a partir de sus hijos originales. El enfoque más obvio es tener un código que llame a wait oa uno de sus parientes en algún lugar después de haber creado un nuevo proceso. Si se espera que el programa cree muchos procesos secundarios que pueden ejecutarse de forma asincrónica y terminar en un orden impredecible, generalmente es bueno crear un controlador para la señal SIGCHLD , llamando a una de las funciones wait -family en un bucle, hasta que no haya un niño no recopilado. quedan datos. Es posible que el proceso padre ignore por completo la terminación de sus hijos y aún así no cree zombies, pero esto requiere la definición explícita de un controlador para SIGCHLD a través de una llamada a sigaction con la opción especial bandera SA_NOCLDWAIT . [3]
Procesos huérfanos
Los procesos huérfanos son una situación opuesta a los procesos zombis, refiriéndose al caso en el que un proceso padre termina antes que sus procesos hijos, que se dice que quedan "huérfanos". A diferencia de la notificación asincrónica de hijo a padre que ocurre cuando un proceso hijo termina (a través del Señal SIGCHLD ), los procesos secundarios no son notificados inmediatamente cuando su padre termina. En cambio, el sistema simplemente redefine el campo "PID padre" en los datos del proceso hijo para que sea el proceso que es el "antepasado" de todos los demás procesos del sistema, cuyo PID generalmente tiene el valor de 1 (uno) y cuyo nombre es tradicionalmente "init". Por lo tanto, se dijo que init "adopta" todos los procesos huérfanos del sistema. [4] [5]
Una suposición algo común por parte de los programadores nuevos en UNIX era que los procesos secundarios de un proceso de terminación serán adoptados por el proceso principal inmediato de este proceso (de ahí el "abuelo" de esos procesos secundarios). Tal suposición era incorrecta, a menos, por supuesto, que "abuelo" fuera el propio init.
Después del kernel 3.4 de Linux, esto ya no es cierto, de hecho, los procesos pueden emitir la llamada al sistema prctl () con la opción PR_SET_CHILD_SUBREAPER y, como resultado, ellos, no el proceso # 1, se convertirán en el padre de cualquiera de sus procesos descendientes huérfanos. Esta es la forma de trabajo de los administradores de servicios modernos y las utilidades de supervisión de demonios, incluidos systemd, upstart y nosh service manager.
Este es un resumen de la página del manual, informando que:
Un subreaper cumple el papel de init (1) para sus procesos descendientes. Cuando un proceso se vuelve huérfano (es decir, su padre inmediato termina), ese proceso se volverá a comparar con el subapilador de antepasados aún vivo más cercano. Posteriormente, las llamadas a getppid () en el proceso huérfano ahora devolverán el PID del proceso del subreaper, y cuando el huérfano termine, será el proceso del subreaper el que recibirá una señal SIGCHLD y podrá esperar (2) en el proceso. para conocer su estado de terminación. [6]
Referencias
- ^ Tanenbaum, Andrew (2007). Sistemas operativos modernos (3ª ed.). Pearson Prentice Hall. pag. 752. ISBN 0136006639.
- ^ Srinivasan, Sundar (1 de septiembre de 2010). "Opciones y futuros de un ingeniero: un adelanto del kernel de Linux - Capítulo 2: Creación de procesos" . Sunnyeves.blogspot.com . Consultado el 30 de abril de 2014 .
- ^ "esperar página de manual - Llamadas al sistema" . www.mankier.com .
- ^ "init es lo primero" .
- ^ "Una descripción general de los procesos de Linux" . IBM. 26 de marzo de 2012.
- ^ "Manual del programador de Linux" .
Este artículo se basa en material extraído del Diccionario gratuito de informática en línea antes del 1 de noviembre de 2008 e incorporado bajo los términos de "renovación de licencias" de la GFDL , versión 1.3 o posterior.