GNU/Linux >> Tutoriales Linux >  >> Linux

Fork vs Clone en 2.6 Kernel Linux

fork() fue la llamada del sistema UNIX original. Solo se puede usar para crear nuevos procesos, no subprocesos. Además, es portátil.

En Linux, clone() es una llamada al sistema nueva y versátil que se puede utilizar para crear un nuevo hilo de ejecución. Dependiendo de las opciones pasadas, el nuevo subproceso de ejecución puede adherirse a la semántica de un proceso UNIX, un subproceso 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 archivos, varios espacios de nombres, controladores de señales, etc., se comparten o copian.

Desde clone() es la llamada al sistema superconjunto, la implementación del fork() el envoltorio de llamada del sistema en glibc en realidad llama a clone() , pero este es un detalle de implementación que los programadores no necesitan conocer. El verdadero fork() real La llamada al sistema todavía existe en el kernel de Linux por razones de compatibilidad con versiones anteriores, aunque 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 utiliza para implementar el pthread_create() Función POSIX para crear hilos.

Los programas portátiles deben llamar a fork() y pthread_create() , no clone() .


Parece que hay dos clone() cosas flotando en Linux 2.6

Hay una llamada al sistema:

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

Este es el "clon()" descrito al hacer man 2 clone .

Si lee esa página del manual lo suficientemente cerca, verá 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 con un nombre idéntico y confuso.

Escribí un programa corto:

#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;
}

Compilado con:c99 -Wall -Wextra y lo ejecutó bajo strace -f para ver qué hacen realmente las llamadas al sistema. Saqué esto de strace en una máquina Linux 2.6.18 (CPU x86_64):

20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0)                     = ?
20098 exit_group(0)

No aparece ninguna llamada de "bifurcación" en el strace producción. El clone() llamada que aparece en el strace la salida tiene argumentos muy diferentes de la página del manual-clon. child_stack=0 ya que el primer argumento es diferente a int (*fn)(void *) .

Parece que el fork(2) la llamada al sistema se implementa en términos de real clone() , al igual que la "función de biblioteca" clone() está implementado. El real clone() tiene un conjunto diferente de argumentos del clon de la página del manual.

Simplistamente, sus declaraciones aparentemente contradictorias sobre fork() y clone() son correctos Sin embargo, el "clon" involucrado es diferente.


fork() es solo un conjunto particular de banderas para la llamada al sistema clone() . clone() es lo suficientemente general como para crear un "proceso" o un "subproceso" o incluso cosas extrañas que se encuentran en algún lugar entre procesos y subprocesos (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 kernel, clone() le da la opción de crear un alias para esa información o copiarla. Los subprocesos corresponden al aliasing, los procesos corresponden a la copia. Especificando combinaciones intermedias de banderas para clone() , puedes crear cosas extrañas que no son subprocesos o procesos. Por lo general, no debería hacer esto, e imagino que hubo cierto debate durante el desarrollo del kernel de Linux sobre si debería permitir un mecanismo tan general como clone() .


Linux
  1. Cómo actualizar Kernel en Linux Desktop

  2. Linux:¿un núcleo corrupto en Linux?

  3. Linux:¿los diferentes kernels de Linux/unix son intercambiables?

  4. La llamada al sistema Linux más rápida

  5. Qué archivo en el kernel especifica fork(), vfork()... para usar la llamada al sistema sys_clone()

¿Linux es un sistema operativo o un kernel?

Núcleo de Linux vs. Núcleo de Mac

Kernel de Linux y sus funciones

Qué hacer en caso de pánico en el kernel de Linux

Guía completa de registro de Linux

Linux – Diagrama de Linux Kernel vs. Herramientas de rendimiento?