Fork-exec es una técnica comúnmente utilizada en Unix mediante la cual un proceso de ejecución genera un nuevo programa.
Descripción
fork()
es el nombre de la llamada al sistema que utiliza el proceso padre para "dividirse" ("bifurcación") en dos procesos idénticos. Después de llamar fork()
, el proceso hijo creado es una copia exacta del padre excepto por el valor de retorno de la llamada fork (). Esto incluye archivos abiertos, estado de registro y todas las asignaciones de memoria, que incluye el código ejecutable del programa. En algunos casos, los dos continúan ejecutando el mismo binario, pero a menudo uno (generalmente el hijo) cambia para ejecutar otro ejecutable binario utilizando la exec()
llamada al sistema.
Cuando un proceso se bifurca, se realiza una copia completa del programa en ejecución en el nuevo proceso. Este nuevo proceso es hijo del proceso padre y tiene un nuevo identificador de proceso (PID). La fork()
función devuelve el PID del niño al proceso padre. La fork()
función devuelve 0 al proceso hijo. Esto permite que los dos procesos idénticos se distingan entre sí.
El proceso padre puede continuar la ejecución o esperar a que se complete el proceso hijo. El niño, después de descubrir que es el niño, se reemplaza completamente por otro programa, de modo que se pierde el código y el espacio de direcciones del programa original.
Si el padre elige esperar a que el niño muera, entonces el padre recibirá el código de salida del programa que ejecutó el niño. Para evitar que el niño se convierta en un zombi, el padre debe llamar a esperar a sus hijos, ya sea periódicamente o al recibir la señal SIGCHLD , que indica que un proceso secundario ha terminado.
También se puede esperar asincrónicamente a que sus hijos terminen, utilizando un controlador de señales para SIGCHLD , si necesitan asegurarse de que todo esté limpio. Aquí hay un ejemplo de un controlador de señales que detecta cualquier señal SIGCHLD entrante y maneja múltiples señales simultáneas recibidas.
limpieza vacía ( señal int ) { while ( waitpid (( pid_t ) ( -1 ), 0 , WNOHANG ) > 0 ) {} }
Cuando el proceso hijo llama exec()
, todos los datos del programa original se pierden y se reemplazan con una copia en ejecución del nuevo programa. Esto se conoce como superposición . Aunque se reemplazan todos los datos, los descriptores de archivo que estaban abiertos en el padre se cierran solo si el programa los ha marcado explícitamente close-on-exec . Esto permite la práctica común de que el padre cree una tubería antes de llamar fork()
y usarla para comunicarse con el programa ejecutado.
Microsoft Windows no es compatible con el modelo fork-exec, ya que no tiene una llamada al sistema análoga a fork()
. La spawn()
familia de funciones declaradas en process.h puede reemplazarlo en los casos en que la llamada a fork()
sea seguida directamente por exec()
.
Cuando se realiza una llamada al sistema fork en WSL , lxss.sys hace parte del trabajo inicial para prepararse para copiar el proceso. Luego llama a las API de NT internas para crear el proceso con la semántica correcta y crear un hilo en el proceso con un contexto de registro idéntico. Finalmente, realiza un trabajo adicional para completar la copia del proceso y reanuda el nuevo proceso para que pueda comenzar a ejecutarse.
- Jack Hammons de Microsoft [1]
Referencias
- "Descriptores de archivo en fork (2) / exec (2)" , Sistemas operativos (Curso 304-427B), Franco Callari, Departamento de Ingeniería Eléctrica, Universidad McGill
- "tenedor y ejecutivo" , Tim Love, Departamento de Ingeniería de la Universidad de Cambridge
- Programación avanzada en el entorno UNIX , W. Richard Stevens , Addison-Wesley ISBN 0-201-56317-7
- Herramientas eléctricas Unix , Jerry Peek, Tim O'Reilly , Mike Loukides, O'Reilly , ISBN 1-56592-260-3