fork()fue la llamada original al sistema UNIX. Solo se puede usar para crear nuevos procesos, no hilos. Además, es portátil.
En Linux, clone()es una nueva y versátil llamada al sistema que se puede usar para crear un nuevo hilo de ejecución. Dependiendo de las opciones pasadas, el nuevo hilo de ejecución puede adherirse a la semántica de un proceso UNIX, un hilo POSIX, algo intermedio o algo completamente diferente (como un contenedor diferente). Puede especificar todo tipo de opciones que dictan si la memoria, los descriptores de archivo, los diversos espacios de nombres, los controladores de señales, etc., se comparten o copian.
Dado que clone()es la llamada al sistema de superconjunto, la implementación del fork()envoltorio de llamada del sistema en glibc realmente llama clone(), pero este es un detalle de implementación que los programadores no necesitan conocer. La fork()llamada real al sistema real todavía existe en el kernel de Linux por razones de compatibilidad con versiones anteriores a pesar de que se ha vuelto redundante, porque los programas que usan versiones muy antiguas de libc, u otra libc además de glibc, podrían usarla.
clone()también se usa para implementar la pthread_create()función POSIX para crear hilos.
Los programas portátiles deben llamar fork()y pthread_create()no clone().
Este es el "clon ()" descrito haciendo man 2 clone.
Si lees esa página de manual lo suficientemente cerca, verás esto:
It is actually a library function layered on top of the
underlying clone() system call.
Aparentemente, se supone que debe implementar subprocesos utilizando la "función de biblioteca" en capas en la llamada al sistema confusamente identificada.
Escribí un breve programa:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
pid_t cpid;
switch (cpid = fork()) {
case 0: // Child process
break;
case -1: // Error
break;
default: // parent process
break;
}
return 0;
}
Lo compilé con: c99 -Wall -Wextray lo ejecuté strace -fpara ver qué hace realmente la bifurcación de llamadas del sistema. straceObtuve esto en una máquina Linux 2.6.18 (CPU x86_64):
No aparece la llamada "fork" en la stracesalida. La clone()llamada que aparece en la stracesalida tiene argumentos muy diferentes del clon de página de manual. child_stack=0como primer argumento es diferente int (*fn)(void *).
Parece que la fork(2)llamada al sistema se implementa en términos realesclone() , al igual que clone()se implementa la "función de biblioteca" . Lo realclone() tiene un conjunto diferente de argumentos del clon de la página de manual.
Simplísticamente, sus dos declaraciones aparentemente contradictorias sobre fork()y clone()son correctas. Sin embargo, el "clon" involucrado es diferente.
"En realidad es una función de biblioteca en capas sobre la llamada al sistema clone () subyacente". - en general, esto se aplica a todas las llamadas al sistema. Los programadores prácticamente siempre invocan funciones en libc que llevan el nombre de la llamada al sistema. Esto se debe a que realizar una llamada real al sistema real directamente desde C requiere magia específica de la plataforma (generalmente forzando una trampa de CPU de algún tipo, depende de la arquitectura ABI) y el código de la máquina es mejor delegarlo en libc.
Celada
1
@Celada: sí, de acuerdo. Es solo que las man 2 clonefrases son exactamente de esa manera, lo que pensé que confundía el tema y evitaba que el interlocutor obtuviera una buena respuesta.
Bruce Ediger
2
Creo que la página de manual significa indicar que la lista de argumentos de la clonefunción de biblioteca difiere sustancialmente de la lista de argumentos aceptada por la llamada al sistema subyacente. Específicamente, la llamada al sistema siempre regresa dos veces en la misma pila, de la manera tradicional fork; Todos los argumentos relacionados con la pila secundaria se manejan estrictamente en el espacio del usuario. Ver por ejemplo sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/…
zwol
1
Quería darle la mejor respuesta a tu respuesta porque es genial, pero la manada me dejó influir y fui con la primera respuesta. Ella obtiene puntos por el tiempo de respuesta. Gracias por tu explicación.
Gregg Leventhal
6
fork()es solo un conjunto particular de indicadores para la llamada al sistema clone(). clone()es lo suficientemente general como para crear un "proceso" o un "hilo" o incluso cosas extrañas que se encuentran en algún punto entre los procesos y los hilos (por ejemplo, diferentes "procesos" que comparten la misma tabla de descriptores de archivos).
Esencialmente, para cada "tipo" de información asociada con un contexto de ejecución en el núcleo, clone()le da la opción de alias esa información o copiarla. Los hilos corresponden al alias, los procesos corresponden a la copia. Al especificar combinaciones intermedias de indicadores para clone(), puede crear cosas extrañas que no son hilos o procesos. Por lo general, no debería hacer esto, e imagino que hubo un debate durante el desarrollo del kernel de Linux sobre si debería permitir un mecanismo tan general como clone().
Parece que hay dos
clone()
cosas flotando en Linux 2.6Hay una llamada al sistema:
Este es el "clon ()" descrito haciendo
man 2 clone
.Si lees esa página de manual lo suficientemente cerca, verás esto:
Aparentemente, se supone que debe implementar subprocesos utilizando la "función de biblioteca" en capas en la llamada al sistema confusamente identificada.
Escribí un breve programa:
Lo compilé con:
c99 -Wall -Wextra
y lo ejecutéstrace -f
para ver qué hace realmente la bifurcación de llamadas del sistema.strace
Obtuve esto en una máquina Linux 2.6.18 (CPU x86_64):No aparece la llamada "fork" en la
strace
salida. Laclone()
llamada que aparece en lastrace
salida tiene argumentos muy diferentes del clon de página de manual.child_stack=0
como primer argumento es diferenteint (*fn)(void *)
.Parece que la
fork(2)
llamada al sistema se implementa en términos realesclone()
, al igual queclone()
se implementa la "función de biblioteca" . Lo realclone()
tiene un conjunto diferente de argumentos del clon de la página de manual.Simplísticamente, sus dos declaraciones aparentemente contradictorias sobre
fork()
yclone()
son correctas. Sin embargo, el "clon" involucrado es diferente.fuente
man 2 clone
frases son exactamente de esa manera, lo que pensé que confundía el tema y evitaba que el interlocutor obtuviera una buena respuesta.clone
función de biblioteca difiere sustancialmente de la lista de argumentos aceptada por la llamada al sistema subyacente. Específicamente, la llamada al sistema siempre regresa dos veces en la misma pila, de la manera tradicionalfork
; Todos los argumentos relacionados con la pila secundaria se manejan estrictamente en el espacio del usuario. Ver por ejemplo sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/…fork()
es solo un conjunto particular de indicadores para la llamada al sistemaclone()
.clone()
es lo suficientemente general como para crear un "proceso" o un "hilo" o incluso cosas extrañas que se encuentran en algún punto entre los procesos y los hilos (por ejemplo, diferentes "procesos" que comparten la misma tabla de descriptores de archivos).Esencialmente, para cada "tipo" de información asociada con un contexto de ejecución en el núcleo,
clone()
le da la opción de alias esa información o copiarla. Los hilos corresponden al alias, los procesos corresponden a la copia. Al especificar combinaciones intermedias de indicadores paraclone()
, puede crear cosas extrañas que no son hilos o procesos. Por lo general, no debería hacer esto, e imagino que hubo un debate durante el desarrollo del kernel de Linux sobre si debería permitir un mecanismo tan general comoclone()
.fuente