Estaba buscando encontrar la diferencia entre estos cuatro en Google y esperaba que hubiera una gran cantidad de información sobre esto, pero realmente no hubo una comparación sólida entre las cuatro llamadas.
Me puse a tratar de compilar una especie de vistazo básico de un vistazo a las diferencias entre estas llamadas al sistema y esto es lo que obtuve. ¿Es correcta toda esta información / me falta algo importante?
Fork
: La llamada fork básicamente hace un duplicado del proceso actual, idéntico en casi todos los sentidos (no todo se copia, por ejemplo, los límites de recursos en algunas implementaciones, pero la idea es crear una copia lo más cercana posible).
El nuevo proceso (hijo) obtiene una ID de proceso diferente (PID) y tiene el PID del proceso anterior (padre) como su PID padre (PPID). Debido a que los dos procesos ahora están ejecutando exactamente el mismo código, pueden determinar cuál es cuál mediante el código de retorno de fork: el niño obtiene 0, el padre obtiene el PID del niño. Esto es todo, por supuesto, suponiendo que la llamada fork funcione; de lo contrario, no se crea ningún elemento secundario y el padre obtiene un código de error.
Vfork
: La diferencia básica entre vfork y fork es que cuando se crea un nuevo proceso con vfork (), el proceso padre se suspende temporalmente y el proceso hijo podría tomar prestado el espacio de direcciones del padre. Este extraño estado de cosas continúa hasta que el proceso secundario sale o llama a execve (), momento en el cual el proceso primario continúa.
Esto significa que el proceso hijo de vfork () debe tener cuidado para evitar modificar inesperadamente las variables del proceso padre. En particular, el proceso secundario no debe regresar de la función que contiene la llamada vfork (), y no debe llamar a exit () (si necesita salir, debe usar _exit (); en realidad, esto también es cierto para el secundario de un tenedor normal ()).
Exec :
La llamada ejecutiva es una forma de reemplazar básicamente todo el proceso actual con un nuevo programa. Carga el programa en el espacio de proceso actual y lo ejecuta desde el punto de entrada. exec () reemplaza el proceso actual con el ejecutable señalado por la función. El control nunca vuelve al programa original a menos que haya un error exec ().
Clone :
Clone, como fork, crea un nuevo proceso. A diferencia de fork, estas llamadas permiten que el proceso secundario comparta partes de su contexto de ejecución con el proceso de llamada, como el espacio de memoria, la tabla de descriptores de archivos y la tabla de manejadores de señales.
Cuando el proceso hijo se crea con clone, ejecuta la aplicación de función fn (arg). (Esto difiere de fork, donde la ejecución continúa en el hijo desde el punto de la llamada fork original). El argumento fn es un puntero a una función que el proceso hijo invoca al comienzo de su ejecución. El argumento arg se pasa a la función fn.
Cuando la aplicación de la función fn (arg) regresa, el proceso secundario finaliza. El número entero devuelto por fn es el código de salida para el proceso secundario. El proceso secundario también puede finalizar explícitamente llamando a exit (2) o después de recibir una señal fatal.
Información obtenida de forma:
- Diferencias entre fork y exec
- http://www.allinterview.com/showanswers/59616.html
- http://www.unixguide.net/unix/programming/1.1.2.shtml
- http://linux.about.com/library/cmd/blcmdl2_clone.htm
¡Gracias por tomarse el tiempo de leer esto! :)
fork()
Linux, y probablemente a todos los BSD) toma prestado el espacio de direcciones de su padre. Todo lo que hace, además de llamarexecve()
o_exit()
tiene un gran potencial para confundir a los padres. En particular, los manejadores deexit()
llamadasatexit()
y otros "finalizadores", p. Ej .: lava los flujos stdio. Regresar de unvfork()
niño podría potencialmente (la misma advertencia que antes) ensuciar la pila de los padres.fork
sistema?Respuestas:
vfork()
Es una optimización obsoleta. Antes de una buena gestión de la memoria,fork()
hacía una copia completa de la memoria de los padres, por lo que era bastante costosa. dado que en muchos casosfork()
se siguió aexec()
, que descarta el mapa de memoria actual y crea uno nuevo, fue un gasto innecesario. Hoy en día,fork()
no copia la memoria; simplemente se configura como "copiar al escribir", por lo quefork()
+exec()
es tan eficiente comovfork()
+exec()
.clone()
es la llamada al sistema utilizada porfork()
. con algunos parámetros, crea un nuevo proceso, con otros, crea un hilo. la diferencia entre ellos es qué estructuras de datos (espacio de memoria, estado del procesador, pila, PID, archivos abiertos, etc.) se comparten o no.fuente
vfork
evita la necesidad de almacenar temporalmente mucha más memoria solo para que uno pueda ejecutarexec
, y todavía es más eficiente quefork
, incluso si no es tan alto. Por lo tanto, se puede evitar tener que comprometer la memoria en exceso para que un programa grande y poderoso pueda generar un proceso secundario. Por lo tanto, no solo aumenta el rendimiento, sino que podría hacerlo factible.exec
.execve()
reemplaza la imagen ejecutable actual con otra cargada desde un archivo ejecutable.fork()
crea un proceso hijo.vfork()
es una versión histórica optimizadafork()
, destinada a utilizarse cuandoexecve()
se llama directamente después defork()
. Resultó funcionar bien en sistemas que no son MMU (dondefork()
no pueden funcionar de manera eficiente) y alfork()
procesar procesos con una gran huella de memoria para ejecutar algún programa pequeño (piense en JavaRuntime.exec()
). POSIX ha estandarizado elposix_spawn()
para reemplazar estos dos últimos usos más modernos devfork()
.posix_spawn()
hace el equivalente de afork()/execve()
, y también permite un poco de malabares fd en el medio. Se supone que debe reemplazarfork()/execve()
, principalmente para plataformas que no son MMU.pthread_create()
crea un nuevo hilo.clone()
es una llamada específica de Linux, que se puede usar para implementar cualquier cosa desdefork()
hastapthread_create()
. Da mucho control. Inspirado enrfork()
.rfork()
es una llamada específica al Plan-9. Se supone que es una llamada genérica, que permite varios grados de intercambio, entre procesos completos y subprocesos.fuente
fork()
- crea un nuevo proceso hijo, que es una copia completa del proceso padre. Los procesos hijo y padre utilizan diferentes espacios de direcciones virtuales, que inicialmente se rellenan con las mismas páginas de memoria. Luego, a medida que se ejecutan ambos procesos, los espacios de direcciones virtuales comienzan a diferir cada vez más, porque el sistema operativo realiza una copia diferida de las páginas de memoria que están siendo escritas por cualquiera de estos dos procesos y asigna copias independientes de las páginas modificadas de memoria para cada proceso. Esta técnica se llama Copiar en escritura (COW).vfork()
- crea un nuevo proceso hijo, que es una copia "rápida" del proceso padre. A diferencia de la llamada al sistemafork()
, los procesos hijo y padre comparten el mismo espacio de dirección virtual. ¡NOTA! Usando el mismo espacio de dirección virtual, tanto el padre como el hijo usan la misma pila, el puntero de la pila y el puntero de instrucciones, como en el caso del clásicofork()
. Para evitar interferencias no deseadas entre padre e hijo, que usan la misma pila, la ejecución del proceso padre se congela hasta que el niño llameexec()
(crear un nuevo espacio de dirección virtual y una transición a una pila diferente) o_exit()
(finalización de la ejecución del proceso )vfork()
es la optimización de (incluso teniendo en cuenta COW), la implementación defork()
modelo "fork-and-exec". Se puede realizar 4-5 veces más rápido que elfork()
, porque a diferencia delfork()
vfork()
la llamada al sistema no incluye la creación de un nuevo espacio de direcciones (la asignación y la configuración de nuevos directorios de páginas).clone()
- Crea un nuevo proceso hijo. Varios parámetros de esta llamada al sistema, especifican qué partes del proceso principal deben copiarse en el proceso secundario y qué partes se compartirán entre ellos. Como resultado, esta llamada al sistema se puede utilizar para crear todo tipo de entidades de ejecución, comenzando desde subprocesos y terminando mediante procesos completamente independientes. De hecho, laclone()
llamada al sistema es la base que se utiliza para la implementaciónpthread_create()
y todas lasfork()
llamadas de la familia del sistema.exec()
- restablece toda la memoria del proceso, carga y analiza el binario ejecutable especificado, configura una nueva pila y pasa el control al punto de entrada del ejecutable cargado. Esta llamada al sistema nunca devuelve el control a la persona que llama y sirve para cargar un nuevo programa al proceso ya existente. Esta llamada alfork()
sistema junto con la llamada del sistema forman un modelo clásico de gestión de procesos UNIX llamado "fork-and-exec".fuente
vfork
son tan débiles que sería legal hacervfork
un sinónimo defork
(y POSIX.1-2008 elimina completamentevfork
de la especificación). Si prueba su código en un sistema que los sinonice (por ejemplo, la mayoría de los BSD posteriores a 4.4 aparte de NetBSD, kernels Linux anteriores a 2.2.0-pre6, etc.), puede funcionar incluso si viola elvfork
contrato y luego explota si lo ejecutas en otro lado Algunos de los que lo simulan confork
(por ejemplo, OpenBSD) aún garantizan que el padre no reanude la ejecución hasta que el hijoexec
o hija_exit
. Es ridículamente no portátil.El fork (), vfork () y clone () todos llaman a do_fork () para hacer el trabajo real, pero con diferentes parámetros.
Para fork, el niño y el padre tienen la tabla de páginas VM independiente, pero desde la eficiencia, fork realmente no copiará ninguna página, solo configura todas las páginas que se pueden escribir para que sean solo de lectura para el proceso hijo. Entonces, cuando el proceso secundario desea escribir algo en esa página, se produce una excepción de página y el núcleo asignará una nueva página clonada de la página anterior con permiso de escritura. Eso se llama "copiar al escribir".
Para vfork, la memoria virtual es exactamente por hijo y padre --- solo por eso, padre e hijo no pueden estar despiertos al mismo tiempo ya que se influirán mutuamente. Por lo tanto, el padre dormirá al final de "do_fork ()" y se despertará cuando el niño llame a exit () o execve () desde entonces tendrá una nueva tabla de páginas. Aquí está el código (en do_fork ()) que el padre duerme.
Aquí está el código (en mm_release () llamado por exit () y execve ()) que despierta al padre.
Para sys_clone (), es más flexible ya que puede ingresar cualquier clone_flags. Entonces pthread_create () llama a esta llamada al sistema con muchos clone_flags:
int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM);
Resumen: fork (), vfork () y clone () crearán procesos secundarios con un montaje diferente de recursos compartidos con el proceso padre. También podemos decir que vfork () y clone () pueden crear hilos (en realidad son procesos, ya que tienen una estructura de tareas independiente) ya que comparten la tabla de páginas VM con el proceso padre.
fuente
en fork (), el proceso hijo o padre se ejecutará en función de la selección de la CPU. Pero en vfork (), seguramente el hijo se ejecutará primero. después de la terminación del niño, el padre ejecutará.
fuente
vfork()
solo se puede implementar comofork()
.pid
): el sistema operativo puede programar el nuevo proceso para que se ejecute en paralelo si tal cosa tiene sentido (por ejemplo, múltiples procesadores). Si por alguna razón necesita que estos procesos se ejecuten en un orden en serie particular, entonces necesita una sincronización adicional que la bifurcación no proporciona; francamente, probablemente ni siquiera quieras un tenedor en primer lugar.vfork()
, el niño corre primero. Está en las páginas del manual; la ejecución de los padres se suspende hasta que el niño muera o fallezcaexec
. Y ninjalj busca el código fuente del núcleo. No hay manera de implementarvfork()
comofork()
porque pasan diferentes argumentos parado_fork()
dentro del núcleo. Sin embargo, puede implementarvfork
con laclone
llamada al sistema