GNU/Linux >> Tutoriels Linux >  >> Linux

Fork vs Clone sur le noyau Linux 2.6

fork() était l'appel système UNIX d'origine. Il ne peut être utilisé que pour créer de nouveaux processus, pas des threads. De plus, il est portable.

Sous Linux, clone() est un nouvel appel système polyvalent qui peut être utilisé pour créer un nouveau fil d'exécution. Selon les options transmises, le nouveau thread d'exécution peut adhérer à la sémantique d'un processus UNIX, d'un thread POSIX, de quelque chose entre les deux ou de quelque chose de complètement différent (comme un conteneur différent). Vous pouvez spécifier toutes sortes d'options indiquant si la mémoire, les descripteurs de fichiers, divers espaces de noms, les gestionnaires de signaux, etc. sont partagés ou copiés.

Depuis clone() est l'appel système du sur-ensemble, l'implémentation du fork() le wrapper d'appel système dans la glibc appelle en fait clone() , mais il s'agit d'un détail d'implémentation que les programmeurs n'ont pas besoin de connaître. Le réel réel fork() L'appel système existe toujours dans le noyau Linux pour des raisons de rétrocompatibilité, même s'il est devenu redondant, car les programmes qui utilisent de très anciennes versions de la libc, ou une autre libc en plus de la glibc, pourraient l'utiliser.

clone() est également utilisé pour implémenter le pthread_create() Fonction POSIX pour créer des threads.

Les programmes portables doivent appeler fork() et pthread_create() , pas clone() .


Il semble qu'il y ait deux clone() les choses qui flottent dans Linux 2.6

Il y a un appel système :

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

C'est le "clone()" décrit en faisant man 2 clone .

Si vous lisez assez attentivement cette page de manuel, vous verrez ceci :

It is actually a library function layered on top of the
underlying clone() system call.

Apparemment, vous êtes censé implémenter le threading en utilisant la "fonction de bibliothèque" superposée à l'appel système portant le même nom.

J'ai écrit un petit programme :

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

Compilé avec :c99 -Wall -Wextra , et l'a exécuté sous strace -f pour voir ce que font réellement les appels système. J'ai obtenu ceci sur strace sur une machine Linux 2.6.18 (processeur 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)

Aucun appel "fork" n'apparaît dans le strace production. Le clone() appel qui apparaît dans le strace output a des arguments très différents de man-page-clone. child_stack=0 car le premier argument est différent de int (*fn)(void *) .

Il semble que le fork(2) l'appel système est implémenté en termes de réel clone() , tout comme la "fonction bibliothèque" clone() est implémenté. Le vrai clone() a un ensemble d'arguments différent de celui de man-page-clone.

De manière simpliste, vos deux déclarations apparemment contradictoires à propos de fork() et clone() sont corrects. Le "clone" impliqué est cependant différent.


fork() est juste un ensemble particulier d'indicateurs pour l'appel système clone() . clone() est assez général pour créer un "processus" ou un "thread" ou même des choses étranges qui se situent quelque part entre les processus et les threads (par exemple, différents "processus" qui partagent la même table de descripteurs de fichiers).

Essentiellement, pour chaque "type" d'informations associées à un contexte d'exécution dans le noyau, clone() vous donne le choix d'aliaser ces informations ou de les copier. Les threads correspondent à l'aliasing, les processus correspondent à la copie. En spécifiant des combinaisons intermédiaires de drapeaux à clone() , vous pouvez créer des choses étranges qui ne sont ni des threads ni des processus. Vous ne devriez généralement pas faire cela, et j'imagine qu'il y a eu un débat lors du développement du noyau Linux pour savoir s'il devrait permettre un mécanisme aussi général que clone() .


Linux
  1. Linux – Noyau :Prise en charge des espaces de noms ?

  2. Linux - Transfert IP du noyau ?

  3. Linux – Un noyau corrompu sous Linux ?

  4. Appeler une fonction de l'espace utilisateur à partir d'un module du noyau Linux

  5. Appel système Linux le plus rapide

Linux est-il un système d'exploitation ou un noyau ?

Le noyau Linux contre. Mac noyau

Le noyau Linux et ses fonctions

Que faire en cas de panique du noyau Linux

Guide complet de journalisation Linux

Linux - Schéma du noyau Linux Vs. Outils de performances ?