clone

CLONE(2)                   Manuel du programmeur Linux                  CLONE(2)



NOM
       clone, __clone2, clone3 - Créer un processus enfant (child)

SYNOPSIS
       /* Prototype de la fonction enveloppe de la glibc */

       #define _GNU_SOURCE
       #include <sched.h>

       int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
                 /* pid_t *parent_tid, void *tls, pid_t *child_tid */ );

       /* Pour le prototype de l'appel système clone() brut, voir REMARQUES */

       long clone3(struct clone_args *cl_args, size_t size);

       Remarque : il n'y pas encore d'enveloppe glibc pour clone3() ; voir les
       REMARQUES.

DESCRIPTION
       Ces appels système créent un nouveau processus « enfant », de façon
       analogue à fork(2).

       Contrairement à fork(2), ces appels système offrent un contrôle plus
       précis du contexte d'exécution partagé entre le processus appelant et son
       enfant. Par exemple, en utilisant ces appels système, l'appelant peut
       contrôler si les deux processus partagent ou non l'espace d'adresse
       virtuel, la table des descripteurs de fichier et celle des gestionnaires
       de signal. Ces appels système permettent également au nouveau processus
       enfant d'aller dans un namespaces(7) à part.

       Remarquez que dans cette page de manuel, le « processus appelant »
       correspond en principe au « processus parent ». Mais voir les
       descriptions de CLONE_PARENT et de CLONE_THREAD ci-dessous.

       Cette page décrit les interfaces suivantes :

       *  Cette page présente à la fois la fonction enveloppe clone() de la
          glibc et l'appel système sous-jacent sur lequel elle s'appuie. Le
          texte principal décrit la fonction enveloppe ; les différences avec
          l'appel système brut sont précisées vers la fin de cette page.

       *  Le nouvel appel système clone3().

       Dans la suite de cette page, le terme « appel clone » est utilisé pour
       évoquer les détails applicables à toutes ces interfaces,

   La fonction enveloppe clone()
       Quand le processus enfant est créé par la fonction enveloppe clone(), il
       débute son exécution par un appel à la fonction vers laquelle pointe
       l'argument fn (cela est différent de fork(2), pour lequel l'exécution
       continue dans le processus enfant à partir du moment de l'appel de
       fork(2)). L'argument arg est passé comme argument de la fonction fn.

       Quand la fonction fn(arg) renvoie, le processus enfant se termine. La
       valeur entière renvoyée par fn est utilisée comme code de retour du
       processus enfant. Ce dernier peut également se terminer de manière
       explicite en invoquant la fonction exit(2) ou après la réception d'un
       signal fatal.

       L'argument stack indique l'emplacement de la pile utilisée par le
       processus enfant. Comme les processus enfant et appelant peuvent partager
       de la mémoire, il n'est généralement pas possible pour l'enfant
       d'utiliser la même pile que son parent. Le processus appelant doit donc
       préparer un espace mémoire pour stocker la pile de son enfant, et
       transmettre à clone un pointeur sur cet emplacement. Les piles croissent
       vers le bas sur tous les processeurs implémentant Linux (sauf le HP PA),
       donc stack doit pointer sur la plus haute adresse de l'espace mémoire
       prévu pour la pile du processus enfant. Remarquez que clone() ne fournit
       aucun moyen pour que l'appelant puisse informer le noyau de la taille de
       la zone de la pile.

       Les paramètres restant à clone() sont décrits ci-dessous.

   clone3()
       L'appel système clone3() fournit un sur-ensemble de la fonctionnalité de
       l'ancienne interface de clone(). Il offre également un certain nombre
       d'améliorations de l'API dont : un espace pour des bits d'attributs
       supplémentaires, une séparation plus propre dans l'utilisation de
       plusieurs paramètres et la possibilité d'indiquer la taille de la zone de
       la pile de l'enfant.

       Comme avec fork(2), clone3() renvoie à la fois au parent et à l'enfant.
       Il renvoie 0 dans le processus enfant et il renvoie le PID de l'enfant
       dans le parent.

       Le paramètre cl_args de clone3() est une structure ayant la forme
       suivante :

           struct clone_args {
               u64 flags;        /* Masque de bit d'attributs */
               u64 pidfd;        /* Où stocker le descripteur de fichier du PID
                                    (pid_t *) */
               u64 child_tid;    /* Où stocker le TID enfant,
                                    dans la mémoire de l'enfant (pid_t *) */
               u64 parent_tid;   /* Où stocker le TID enfant,
                                    dans la mémoire du parent (int *) */
               u64 exit_signal;  /* Signal à envoyer au parent quand
                                    l'enfant se termine */
               u64 stack;        /* Pointeur vers l'octet le plus faible de la pile */
               u64 stack_size;   /* Taille de la pile */
               u64 tls;          /* Emplacement du nouveau TLS */
               u64 set_tid;      /* Pointeur vers un tableau pid_t
                                    (depuis Linux 5.5) */
               u64 set_tid_size; /* Nombre d'éléments dans set_tid
                                    (depuis Linux 5.5) */
               u64 cgroup;       /* Descripteur de fichier du cgroup cible
                                    de l'enfant (depuis Linux 5.7) */
           };

       Le paramètre size fourni à clone3() doit être initialisé à la taille de
       cette structure (l'existence du paramètre size autorise des extensions
       futures de la structure clone_args).

       La pile du processus enfant est indiquée avec cl_args.stack, qui pointe
       vers l'octet le plus faible de la zone de la pile, et avec
       cl_args.stack_size, qui indique la taille de la pile en octets. Si
       l'attribut CLONE_VM est indiqué (voir ci-dessous), une pile doit être
       explicitement allouée et indiquée. Sinon, ces deux champs peuvent valoir
       NULL et 0, ce qui amène l'enfant à utiliser la même zone de pile que son
       parent (dans l'espace d'adressage virtuel de son propre enfant).

       Les autres champs du paramètre cl_args sont abordés ci-dessous.

   Équivalence entre les paramètres de clone() et de clone3()
       Contrairement à l'ancienne interface clone(), où les paramètres sont
       passés individuellement, ceux de la nouvelle interface clone3() sont
       empaquetés dans la structure clone_args présentée ci-dessus. Cette
       structure permet de passer un ensemble d'informations à l’aide des
       arguments de clone().

       Le tableau suivant montre l'équivalence entre les paramètres de clone()
       et les champs du paramètre clone_args fournis à clone3() :

              clone()             clone3()        Notes
                                  Champ cl_args
              attributs & ~0xff   attributs       Pour la plupart des attributs ; détails ci-dessous
              parent_tid          pidfd           Voir CLONE_PIDFD
              child_tid           child_tid       Voir CLONE_CHILD_SETTID
              parent_tid          parent_tid      Voir CLONE_PARENT_SETTID
              attributs & 0xff    exit_signal
              pile                pile
              ---                 stack_size
              tls                 tls             Voir CLONE_SETTLS
              ---                 set_tid         Voir ci-dessous pour des détails
              ---                 set_tid_size
              ---                 cgroup          Voir CLONE_INTO_CGROUP

   Signal de fin de l'enfant
       Quand le processus enfant se termine, un signal peut être envoyé au
       parent. Le signal de fin est indiqué dans l'octet de poids faible de
       flags (clone()) ou dans cl_args.exit_signal (clone3()). Si ce signal est
       différent de SIGCHLD, le processus parent doit également spécifier les
       options __WALL ou __WCLONE lorsqu'il attend la fin de l'enfant avec
       wait(2). Si aucun signal n'est indiqué (donc zéro), le processus parent
       ne sera pas notifié de la terminaison de l'enfant.

   Le tableau set_tid
       Par défaut, le noyau choisit le PID séquentiel suivant pour le nouveau
       processus dans chacun des espaces de noms du PID où il est présent. Lors
       de la création d'un processus avec clone3(), le tableau set_tid (depuis
       Linux 5.5) peut être utilisé pour sélectionner des PID spécifiques pour
       le processus dans tout ou partie des espaces de noms où il est présent.
       Si le PID du processus nouvellement créé ne doit être positionné que dans
       l'espace de noms du processus actuel ou dans celui du PID nouvellement
       créé (si flags contient CLONE_NEWPID), le premier élément du tableau
       set_tid doit être le PID souhaité et set_tid_size doit valoir 1.

       Si le PID du processus nouvellement créé doit avoir une certaine valeur
       dans plusieurs espaces de noms de PID, le tableau set_tid peut avoir
       plusieurs entrées. La première entrée définit le PID de l'espace de noms
       le plus imbriqué, puis chacune des entrées suivantes contient le PID de
       l'espace de noms supérieur correspondant. Le nombre d'espaces de noms de
       PID où un PID doit être positionné est défini par set_tid_size, qui ne
       peut pas être plus grand que le nombre d'espaces de noms de PID
       imbriqués.

       Pour créer un processus dont les PID suivants s'inscrivent dans la
       hiérarchie de l'espace de noms de PID :

              Niveau esp. noms du PID   PID demandé   Notes
              0                         31496         Espace de noms du PID le plus à l'extérieur
              1                         42
              2                         7             Espace de noms du PID le plus à l'intérieur

       Positionner le tableau sur :

           set_tid[0] = 7;
           set_tid[1] = 42;
           set_tid[2] = 31496;
           set_tid_size = 3;

       Si seuls les PID des deux espaces de noms de PID intermédiaires doivent
       être indiqués, positionnez le tableau sur :

           set_tid[0] = 7;
           set_tid[1] = 42;
           set_tid_size = 2;

       Le PID dans un espace de noms de PID en dehors des deux espaces de noms
       intermédiaires sera sélectionné de la même manière qu'on sélectionne
       n'importe quel autre PID.

       La fonctionnalité set_tid exige CAP_SYS_ADMIN dans tous les espaces de
       noms appartenant à l'utilisateur dans les espaces de noms du processus
       cible.

       Les appelants ne peuvent choisir qu'un PID supérieur à 1 dans un espace
       de noms de PID donné, si un processus init (à savoir un processus dont le
       PID est 1) existe déjà dans cet espace de noms. Sinon, l'entrée du PID
       dans cet espace de noms de PID doit valoir 1.

   Le masque flags
       Tant clone() que clone3() permettent d'utiliser un masque de bit flags
       pour modifier leur comportement, et elles permettent à l'appelant
       d'indiquer ce qui est partagé entre le processus appelant et son enfant.
       Ce masque de bit - le paramètre flags de clone() ou le champ
       cl_args.flags passé à clone3() - est désigné comme le masque flags dans
       le reste de cette page.

       Le masque flags est indiqué comme un OU bit à bit de zéro ou plus des
       constantes ci-dessous. Sauf explicitement indiqué, ces attributs sont
       disponibles (et ont le même effet) dans clone() et dans clone3().

       CLONE_CHILD_CLEARTID (depuis Linux 2.5.49)
              Effacer (zéro) l'ID du thread enfant situé là où pointe child_tid
              (clone()) ou cl_args.child_tid (clone3()) dans la mémoire de
              l'enfant lorsqu'il existe, et provoquer le réveil avec le futex à
              cette adresse. L'adresse concernée peut être modifiée par l'appel
              système set_tid_address(2). Cela est utilisé dans les
              bibliothèques de gestion de threads.

       CLONE_CHILD_SETTID (depuis Linux 2.5.49)
              Enregistrer l'ID du thread de l'enfant là où pointe child_tid
              ((clone()) ou cl_args.child_tid (clone3()) dans la mémoire de
              l'enfant. L'opération d'enregistrement se termine avant que
              l'appel clone ne redonne le contrôle à l'espace utilisateur dans
              le processus enfant (remarquez que l'opération d'enregistrement se
              termine avant que l'appel clone ne renvoie au processus parent, ce
              qui sera pertinent si l'attribut CLONE_VM est également utilisé).

       CLONE_CLEAR_SIGHAND (depuis Linux 5.5)
              Par défaut, l'état des signaux du thread de l'enfant est le même
              que celui du parent. Si cet attribut est positionné, tous les
              signaux gérés par le parent sont réinitialisés à leur état par
              défaut (SIG_DFL) dans l'enfant.

              Indiquer cet attribut avec CLONE_SIGHAND n'a pas de sens et n'est
              pas autorisé.

       CLONE_DETACHED (historique)
              Pendant un moment (pendant la série de versions au cours du
              développement de Linux 2.5), il y a eu un attribut CLONE_DETACHED,
              avec lequel le parent ne recevait pas de signal quand l'enfant se
              terminait. Au final, l'effet de cet attribut a été inhibé par
              l'attribut CLONE_THREAD et quand Linux 2.6.0 a été publié, cet
              attribut n'avait pas d'effet. À partir de Linux 2.6.2, il n'a plus
              été nécessaire de fournir cet attribut avec CLONE_THREAD.

              Cet attribut est toujours défini, mais il est généralement ignoré
              lors d'un appel clone(). Toutefois, voir la description de
              CLONE_PIDFD pour certaines exceptions.

       CLONE_FILES (depuis Linux 2.0)
              Si l'attribut CLONE_FILES est positionné, le processus appelant et
              le processus enfant partagent la même table de descripteurs de
              fichier. Tout descripteur créé par un processus est également
              valide pour l'autre processus. De même si un processus ferme un
              descripteur, ou modifie ses attributs (en utilisant l'opération
              fcntl(2) F_SETFD), l'autre processus en est aussi affecté. Si un
              processus qui partage une table de descripteurs de fichier appelle
              execve(2), sa table est dupliquée (non partagée).

              Si CLONE_FILES n'est pas positionné, le processus enfant hérite
              d'une copie des descripteurs de fichier ouverts par l'appelant au
              moment de l'appel clone(). Les opérations d'ouverture et de
              fermeture ou de modification d'attributs du descripteur de fichier
              subséquentes, effectuées par le processus appelant ou son enfant,
              ne concernent pas l'autre processus. Remarquez toutefois que les
              copies des descripteurs de fichier dans l'enfant sont associées
              aux mêmes descriptions de fichiers ouverts que les descripteurs de
              fichier correspondants dans le processus appelant, partageant
              ainsi les attributs de position et d’états du fichier (consultez
              open(2)).

       CLONE_FS (depuis Linux 2.0)
              Si l'attribut CLONE_FS est positionné, le processus appelant et le
              processus enfant partagent les mêmes informations concernant le
              système de fichiers. Cela inclut la racine du système de fichiers,
              le répertoire de travail, et l'umask. Tout appel à chroot(2),
              chdir(2) ou umask(2) effectué par un processus aura également
              influence sur l'autre processus.

              Si CLONE_FS n'est pas positionné, le processus enfant travaille
              sur une copie des informations de l'appelant concernant le système
              de fichiers au moment de l'appel clone. Les appels à chroot(2),
              chdir(2), umask(2) effectués ensuite par un processus n'affectent
              pas l'autre processus.

       CLONE_INTO_CGROUP (depuis Linux 5.7)
              Par défaut, un processus enfant est mis dans le même cgroup
              version 2 que son parent. L'attribut CLONE_INTO_CGROUP permet au
              processus enfant d'être créé dans un cgroup version 2 différent
              (remarquez que CLONE_INTO_CGROUP n'a d'effet que sur les cgroup
              version 2).

              Pour mettre le processus enfant dans un cgroup différent,
              l'appelant indique CLONE_INTO_CGROUP dans cl_args.flags et passe
              un descripteur de fichier qui se rapporte à un cgroup version 2 du
              champ cl_args.cgroup (le descripteur de fichier peut être obtenu
              en ouvrant un répertoire cgroup v2, en utilisant l'attribut
              O_RDONLY ou O_PATH). Remarquez que toutes les restrictions
              habituelles (décrites dans cgroups(7)) quant au positionnement
              d'un processus dans un cgroup version 2 s'appliquent.

              Voici certains des cas d'utilisation possibles de
              CLONE_INTO_CGROUP :

              *  Créer un processus dans un autre cgroup que celui du parent
                 permet au gestionnaire de service de placer directement de
                 nouveaux services dans des cgroup dédiés. Cela élimine les
                 contraintes comptables qui existeraient si le processus enfant
                 était créé d'abord dans le même cgroup que le parent puis
                 déplacé dans un cgroup cible. De plus, la création d'un
                 processus enfant directement dans un cgroup cible coûte
                 beaucoup moins cher que de déplacer le processus enfant dans le
                 cgroup cible après l'avoir créé.

              *  L'attribut CLONE_INTO_CGROUP permet également la création de
                 processus enfants gelés en les créant dans un cgroup gelé (voir
                 cgroups(7) pour une description des contrôleurs de gel).

              *  Pour les applications threadées (voire même les implémentations
                 de thread qui utilisent des cgroup pour limiter les threads
                 individuels), il est possible d'établir une couche de cgroup
                 fixe avant de créer chaque thread directement dans son cgroup
                 cible.

       CLONE_IO (depuis Linux 2.6.25)
              Si CLONE_IO est défini, alors le nouveau processus partage un
              contexte d'entrées-sorties avec le processus appelant. Si cet
              attribut n'est pas défini, alors (comme pour fork(2)) le nouveau
              processus a son propre contexte d'entrées-sorties.

              Le contexte d'entrées-sorties correspond à la visibilité que
              l'ordonnanceur de disques a des entrées-sorties (c'est-à-dire, ce
              que l'ordonnanceur d'entrées-sorties utilise pour modéliser
              l'ordonnancement des entrées-sorties d'un processus). Si des
              processus partagent le même contexte d'entrées-sorties, ils sont
              traités comme un seul par l'ordonnanceur d'entrées-sorties. Par
              conséquent, ils partagent le même temps d'accès aux disques. Pour
              certains ordonnanceurs d'entrées-sorties, si deux processus
              partagent un contexte d'entrées-sorties, ils seront autorisés à
              intercaler leurs accès disque. Si plusieurs threads utilisent des
              entrées-sorties pour le même processus (aio_read(3), par exemple),
              ils devraient utiliser CLONE_IO pour obtenir de meilleurs
              performances d'entrées-sorties.

              Si le noyau n'a pas été configuré avec l'option CONFIG_BLOCK, cet
              attribut n'a aucun effet.

       CLONE_NEWCGROUP (depuis Linux 4.6)
              Créer le processus dans un nouvel espace de noms cgroup. Si cet
              attribut n'est pas invoqué, alors (comme pour fork(2)) le
              processus est créé dans le même espace de noms cgroup que le
              processus appelant.

              Pour plus d'informations sur les espaces de noms cgroup, consultez
              cgroup_namespaces(7).

              Seul un processus disposant de privilèges (CAP_SYS_ADMIN) peut
              utiliser CLONE_NEWCGROUP.

       CLONE_NEWIPC (depuis Linux 2.6.19)
              Si CLONE_NEWIPC est invoqué, alors le processus est créé dans un
              nouvel espace de noms utilisateur IPC. Si cet attribut n'est pas
              invoqué, alors (comme pour fork(2)) le processus est créé dans le
              même espace de noms utilisateur IPC que le processus appelant.

              Pour plus d'informations sur les espaces de noms IPC, reportez
              vous à ipc_namespaces(7).

              Seul un processus disposant de privilèges (CAP_SYS_ADMIN) peut
              utiliser CLONE_NEWIPC. Cet attribut ne peut pas être employé en
              association avec CLONE_SYSVSEM.

       CLONE_NEWNET (depuis Linux 2.6.24)
              (L'implémentation de cet attribut n'est complète que depuis le
              noyau 2.6.29.)

              Si CLONE_NEWNET est invoqué, alors le processus est créé dans un
              nouvel espace de noms réseau. Si cet attribut n'est pas invoqué,
              alors (comme pour fork(2)) le processus est créé dans le même
              espace de noms réseau que le processus appelant.

              Pour plus d'informations sur les espaces de noms réseau, reportez
              vous à network_namespaces(7).

              Seul un processus disposant de privilèges (CAP_SYS_ADMIN) peut
              appeler CLONE_NEWNET.

       CLONE_NEWNS (depuis Linux 2.4.19)
              Si l'attribut CLONE_NEWNS est invoqué, l'enfant cloné démarre dans
              un nouvel espace de noms montage, initialisé avec une copie de
              l'espace de noms du parent. Si CLONE_NEWNS n'est pas invoqué,
              alors l'enfant existe dans le même espace de noms montage que le
              parent.

              Pour plus d'informations sur les espaces de noms montage,
              consultez namespaces(7) et mount_namespaces(7).

              Seul un processus disposant de privilèges (CAP_SYS_ADMIN) peut
              utiliser l'attribut CLONE_NEWNS. Il n'est pas possible de
              spécifier à la fois CLONE_NEWNS et CLONE_FS pour le même appel
              clone.

       CLONE_NEWPID (depuis Linux 2.6.24)
              Si CLONE_NEWPID est invoqué, alors le processus est créé dans un
              nouvel espace de noms PID. Si cet attribut n'est pas invoqué,
              alors (comme pour fork(2)) le processus est créé dans le même
              espace de noms PID que le processus appelant.

              Pour plus d'informations sur les espaces de noms PID, consultez
              namespaces(7) et pid_namespaces(7).

              Seul un processus disposant de privilèges (CAP_SYS_ADMIN) peut
              utiliser CLONE_NEWPID. Cet attribut ne peut pas être utilisé en
              association avec CLONE_THREAD ou avec CLONE_PARENT.

       CLONE_NEWUSER
              (Cet attribut est apparu dans clone() pour la première fois dans
              Linux 2.6.23, les sémantiques actuelles de clone() ont été
              ajoutées dans Linux 3.5, et les derniers modules rendant les
              espaces de noms utilisateur complètement opérationnels sont
              apparus dans Linux 3.8.)

              Si CLONE_NEWUSER est invoqué, alors le processus est créé dans un
              nouvel espace de noms utilisateur. Si cet attribut n'est pas
              invoqué, alors (comme pour fork(2)) le processus est créé dans le
              même espace de noms utilisateur que le processus appelant.

              Pour plus d'informations sur les espaces de noms utilisateur,
              consultez namespaces(7) et user_namespaces(7).

              Avant Linux 3.8, les processus appelant devaient disposer de trois
              capacités pour utiliser CLONE_NEWUSER :  CAP_SYS_ADMIN, CAP_SETUID
              et CAP_SETGID.  À partir de Linux 3.8, il n'est plus nécessaire de
              disposer de privilèges pour créer des espaces de noms utilisateur.

              Cet attribut ne peut pas être utilisé en association avec
              CLONE_THREAD ou avec CLONE_PARENT. Pour des raisons de sécurité,
              CLONE_NEWUSER ne peut pas être utilisé en association avec
              CLONE_FS.

       CLONE_NEWUTS (depuis Linux 2.6.19)
              Si CLONE_NEWUTS est défini, créez le processus dans un nouvel
              espace de noms UTS, dont les identifiants sont initialisés en
              dupliquant les identifiants de l'espace de noms UTS du processus
              appelant. Si cet attribut n'est pas défini, alors (comme pour
              fork(2)) le processus est créé dans le même espace de noms UTS que
              le processus appelant.

              Pour obtenir plus d'informations sur les espaces de noms UTS,
              consultez namespaces(7).

              Seul un processus disposant de privilèges (CAP_SYS_ADMIN) peut
              utiliser CLONE_NEWUTS.

       CLONE_PARENT (depuis Linux 2.3.12)
              Si CLONE_PARENT est présent, le parent du nouvel enfant (comme il
              est indiqué par getppid(2)) sera le même que celui du processus
              appelant.

              Si CLONE_PARENT n'est pas fourni, alors (comme pour fork(2)) le
              parent du processus enfant sera le processus appelant.

              Remarquez que c'est le processus parent, tel qu'indiqué par
              getppid(2), qui est notifié lors de la fin de l'enfant. Ainsi, si
              CLONE_PARENT est présent, alors c'est le parent du processus
              appelant, et non ce dernier, qui sera notifié.

              L'attribut CLONE_PARENT ne peut pas être utilisé dans des appels
              clone par le processus d'initialisation global (PID 1 dans
              l'espace de noms PID initial) et par les processus initiaux dans
              les autres espaces de noms PID. Cette restriction empêche la
              création d'arbres de processus à plusieurs racines ou de zombies
              non récupérables dans l'espace de noms PID initial.

       CLONE_PARENT_SETTID (depuis Linux 2.5.49)
              Enregistrer l'ID du thread enfant à l'endroit vers lequel pointe
              parent_tid (clone()) ou cl_args.parent_tid (clone3()) dans la
              mémoire du parent (dans Linux 2.5.32-2.5.48 il y a un attribut
              CLONE_SETTID qui fait cela). L'opération d'enregistrement s'achève
              avant que l'opération clone ne donne le contrôle à l'espace
              utilisateur.

       CLONE_PID (Linux 2.0 à 2.5.15)
              Si l'attribut CLONE_PID est positionné, les processus appelant et
              enfant ont le même numéro de processus. C'est bien pour hacker le
              système, mais autrement il n'est plus utilisé. Depuis Linux
              2.3.21, cet attribut ne peut être utilisé que par le processus de
              démarrage du système (PID 0). Il a disparu dans Linux 2.5.16. Si
              bien que le noyau ignorait silencieusement le bit s'il était
              indiqué dans le masque flags. Bien plus tard, le même bit a été
              recyclé pour être utilisé comme attribut de CLONE_PIDFD.

       CLONE_PIDFD (depuis Linux 5.2)
              Si cet attribut est indiqué, un descripteur de fichier PID
              renvoyant au processus enfant est alloué et placé à un endroit
              donné dans la mémoire du parent. L'attribut close-on-exec est
              positionné sur ce nouveau descripteur de fichier. Les descripteurs
              de fichier PID peuvent être utilisés pour des objectifs décrits
              dans pidfd_open(2).

              *  Quand on utilise clone3(), le descripteur de fichier PID est
                 placé à un endroit vers lequel pointe cl_args.pidfd.

              *  Quand on utilise clone(), le descripteur de fichier PID est
                 placé à un endroit vers lequel pointe parent_tid. Comme le
                 paramètre parent_tid est utilisé pour renvoyer le descripteur
                 de fichier PID, CLONE_PIDFD ne peut pas être utilisé avec
                 CLONE_PARENT_SETTID lors d'un appel clone().

              Il n'est pas possible actuellement d'utiliser cet attribut avec
              CLONE_THREAD. Cela veut dire que le processus identifié par le
              descripteur de fichier PID sera toujours un leader dans le groupe
              de threads.

              Si l'attribut obsolète CLONE_DETACHED est indiqué avec CLONE_PIDFD
              lors d'un appel à clone(), une erreur est renvoyée. Une erreur se
              produit aussi si CLONE_DETACHED est spécifié lors d'un appel à
              clone3(). Ce comportement garantit que le bit qui correspond à
              CLONE_DETACHED pourra être utilisé à l'avenir pour des
              fonctionnalités supplémentaires du descripteur de fichier PID.

       CLONE_PTRACE (depuis Linux 2.2)
              Si l'attribut CLONE_PTRACE est positionné et si l'appelant est
              suivi par un débogueur, alors l'enfant sera également suivi
              (consultez ptrace(2)).

       CLONE_SETTLS (depuis Linux 2.5.32)
              Le descripteur TLS (Thread Local Storage) est positionné sur tls.

              L'interprétation de tls et les effets qui en découlent dépendent
              de l'architecture. Sur x86, tls est interprété comme une struct
              user_desc * (voir set_thread_area(2)). Sur x86-64, il s'agit de la
              nouvelle valeur à positionner pour le registre de base %fs (voir
              le paramètre ARCH_SET_FS de arch_prctl(2)). Sur les architectures
              ayant un registre TLS dédié, il s'agit de la nouvelle valeur de ce
              registre.

              L'utilisation de cet attribut exige une connaissance détaillée et
              n'est généralement pas souhaitable, sauf dans l'implémentation de
              bibliothèques de gestion des threads.

       CLONE_SIGHAND (depuis Linux 2.0)
              Si l'attribut CLONE_SIGHAND est positionné, le processus appelant
              et le processus enfant partagent la même table de gestionnaires de
              signaux. Si l'appelant, ou l'enfant, appelle sigaction(2) pour
              modifier le comportement associé à un signal, ce comportement est
              également changé pour l'autre processus. Néanmoins, l'appelant et
              l'enfant ont toujours des masques de signaux distincts, et leurs
              ensembles de signaux bloqués sont indépendants. L'un des processus
              peut donc bloquer ou débloquer un signal en utilisant
              sigprocmask(2) sans affecter l'autre processus.

              Si CLONE_SIGHAND n'est pas utilisé, le processus enfant hérite
              d'une copie des gestionnaires de signaux de l'appelant lors de
              l'invocation de clone(). Les appels à sigaction(2) effectués
              ensuite depuis un processus n'ont pas d'effets sur l'autre
              processus.

              Depuis Linux 2.6.0, le masque flags doit aussi inclure CLONE_VM si
              CLONE_SIGHAND est spécifié

       CLONE_STOPPED (depuis Linux 2.6.0)
              Si l'attribut CLONE_STOPPED est positionné, l'enfant est
              initialement stoppé (comme s'il avait reçu le signal SIGSTOP), et
              doit être relancé en lui envoyant le signal SIGCONT.

              Cet attribut a été rendu obsolète par Linux 2.6.25, puis il a été
              supprimé dans Linux 2.6.38. Depuis lors, le noyau l'ignore
              silencieusement sans erreur. À partir de Linux 4.6, le même bit a
              été réutilisé comme attribut de CLONE_NEWCGROUP.

       CLONE_SYSVSEM (depuis Linux 2.5.10)
              Si CLONE_SYSVSEM est positionné, l'enfant et le processus appelant
              partagent la même liste de compteurs « undo » pour les sémaphores
              System V (consultez semop(2)). Dans ce cas, cette liste regroupe
              toutes les valeurs semadj des processus partageant cette liste, et
              les modifications des sémaphores sont effectuées seulement lorsque
              le dernier processus de la liste se termine (ou cesse de partager
              la liste en invoquant unshare(2)). Si cet attribut n'est pas
              utilisé, l'enfant a une liste « undo » séparée, initialement vide.

       CLONE_THREAD (depuis Linux 2.4.0)
              Si CLONE_THREAD est présent, l'enfant est placé dans le même
              groupe de threads que le processus appelant. Afin de rendre
              l'explication de CLONE_THREAD plus lisible, le terme « thread »
              est utilisé pour parler des processus dans un même groupe de
              threads.

              Les groupes de threads sont une fonctionnalité ajoutée dans Linux
              2.4 pour supporter la notion POSIX d'ensemble de threads
              partageant un même PID. En interne, ce PID partagé est appelé
              identifiant de groupe de threads (TGID).Depuis Linux 2.4, l'appel
              getpid(2) renvoie l'identifiant du groupe de thread de l'appelant.

              Les threads dans un groupe peuvent être distingués par leur
              identifiant de thread (TID, unique sur le système). Le TID d'un
              nouveau thread est renvoyé par clone() au processus appelant, et
              un thread peut obtenir son propre TID en utilisant gettid(2).

              Quand clone est appelé sans positionner CLONE_THREAD, le nouveau
              thread est placé dans un nouveau groupe de thread dont le TGID est
              identique au TID du nouveau thread. Ce thread est le leader du
              nouveau groupe.

              Un nouveau thread créé en utilisant CLONE_THREAD a le même
              processus parent que l'appelant de clone() (de même qu'avec
              CLONE_PARENT), ainsi les appels à getppid(2) renvoient la même
              valeur à tous les threads dans un même groupe. Lorsqu'un thread
              créé avec CLONE_THREAD termine, le thread qui a appelé clone()
              pour le créer ne reçoit pas le signal SIGCHLD (ou autre
              notification de terminaison) ; de même, l'état d'un tel thread ne
              peut pas être obtenu par wait(2). Le thread est dit détaché.

              Lorsque tous les threads d'un groupe de threads terminent, le
              processus parent du groupe reçoit un signal SIGCHLD (ou autre
              indicateur de terminaison).

              Si l'un des threads dans un groupe de threads appelle execve(2),
              tous les threads sauf le leader sont tués, et le nouveau programme
              est exécuté dans le leader du groupe de threads.

              Si l'un des threads dans un groupe crée un enfant avec fork(2),
              n'importe lequel des threads du groupe peut utiliser wait(2) sur
              cet enfant.

              Depuis Linux 2.5.35, le masque flags doit aussi inclure
              CLONE_SIGHAND si CLONE_THREAD est spécifié (et remarquez que
              depuis Linux 2.6.0, CLONE_SIGHAND a également besoin de CLONE_VM).

              Les gestions de signaux sont définies au niveau des processus : si
              un signal sans gestionnaire est reçu par un thread, il affectera
              (tuera, stoppera, relancera, ou sera ignoré par) tous les membres
              du groupe de threads.

              Chaque thread a son propre masque de signal, tel que défini par
              sigprocmask(2).

              Un signal peut être adressé à un processus ou à un thread. S'il
              s'adresse à un processus, il cible un groupe de threads
              (c'est-à-dire un TGID), et il est envoyé à un thread choisi
              arbitrairement parmi ceux ne bloquant pas les signaux. Un signal
              peut s'adresser à un processus car il est généré par le noyau pour
              d'autres raisons qu'une exception matériel, ou parce qu'il a été
              envoyé en utilisant kill(2) ou sigqueue(3). Si un signal s'adresse
              à un thread, il cible (donc est envoyé) à un thread spécifique. Un
              signal peut s'adresser à un thread du fait d'un envoi par
              tgkill(2) ou pthread_sigqueue(3), ou parce que le thread a exécuté
              une instruction en langage machine qui a provoqué une exception
              matériel (comme un un accès invalide en mémoire, provoquant
              SIGSEGV, ou une exception de virgule flottante provoquant un
              SIGFPE).

              Un appel à sigpending(2) renvoie un jeu de signaux qui réunit les
              signaux en attente adressés au processus et ceux en attente pour
              le thread appelant.

              Si un signal adressé à un processus est envoyé à un groupe de
              threads, et si le groupe a installé un gestionnaire pour ce
              signal, alors le gestionnaire sera exécuté dans exactement un des
              membres du groupe de threads, choisi de façon arbitraire parmi
              ceux qui n'ont pas bloqué ce signal. Si plusieurs threads dans un
              groupe attendent le même signal en utilisant sigwaitinfo(2), le
              noyau choisira arbitrairement l'un d'entre eux pour recevoir le
              signal.

       CLONE_UNTRACED (depuis Linux 2.5.46)
              Si l'attribut CLONE_UNTRACED est positionné, alors un processus
              traçant le parent ne peut pas forcer CLONE_PTRACE pour cet enfant.

       CLONE_VFORK (depuis Linux 2.2)
              Si le bit CLONE_VFORK est actif, l'exécution du processus appelant
              est suspendue jusqu'à ce que l'enfant libère ses ressources de
              mémoire virtuelle par un appel execve(2) ou _exit(2) (comme avec
              vfork(2)).

              Si CLONE_VFORK n'est pas indiqué, alors les deux processus sont
              ordonnancés à partir de la fin de l'appel, et l'application ne
              devrait pas considérer que l'ordre d'exécution est déterminé dans
              un ordre particulier.

       CLONE_VM (depuis Linux 2.0)
              Si le bit CLONE_VM est actif, le processus appelant et le
              processus enfant s'exécutent dans le même espace mémoire. En
              particulier, les écritures en mémoire effectuées par l'un des
              processus sont visibles par l'autre. De même toute projection en
              mémoire, ou toute suppression de projection, effectuée avec
              mmap(2) ou munmap(2) par l'un des processus affectera également
              l'autre processus.

              Si CLONE_VM n'est pas actif, le processus enfant utilisera une
              copie distincte de l'espace mémoire de l'appelant au moment de
              l'appel clone. Les écritures ou les associations/désassociations
              de fichiers en mémoire effectuées par un processus n'affectent pas
              l'autre processus, comme cela se passe avec fork(2).

VALEUR RENVOYÉE
       En cas de réussite, le TID du processus enfant est renvoyé dans le thread
       d'exécution de l'appelant. En cas d'échec, -1 est renvoyé dans le
       contexte de l'appelant, aucun enfant n'est créé, et errno contiendra le
       code d'erreur.

ERREURS
       EAGAIN Trop de processus en cours d'exécution. Consultez fork(2).

       EBUSY (clone3() seulement)
              CLONE_INTO_CGROUP était indiqué dans cl_args.flags, mais le
              descripteur de fichier indiqué dans cl_args.cgroup se rapporte à
              un cgroup version 2 où un contrôleur de domaine est activé.

       EEXIST (clone3() seulement)
              Un (ou plusieurs) PID indiqué dans le set_tid existe déjà dans
              l'espace de noms PID correspondant.

       EINVAL Tant CLONE_SIGHAND que CLONE_CLEAR_SIGHAND ont été indiquées dans
              le masque flags.

       EINVAL CLONE_SIGHAND a été spécifié dans le masque flags, mais pas
              CLONE_VM (depuis Linux 2.6.0).

       EINVAL CLONE_THREAD a été spécifié dans le masque flags, mais pas
              CLONE_SIGHAND  (depuis Linux 2.5.35).

       EINVAL CLONE_THREAD a été indiqué dans le masque flags mais le processus
              actuel avait appelé unshare(2) avec l'attribut CLONE_NEWPID ou il
              utilisait setns(2) pour se réassocier à l'espace de noms PID.

       EINVAL Tant CLONE_FS que CLONE_NEWNS ont été indiqués dans le masque
              flags.

       EINVAL (depuis Linux 3.9)
              Tant CLONE_NEWUSER que CLONE_FS ont été indiqués dans le masque
              flags.

       EINVAL Tant CLONE_NEWIPC que CLONE_SYSVSEM ont été indiqués dans le
              masque flags.

       EINVAL CLONE_NEWPID ou CLONE_NEWUSER, et CLONE_THREAD ou CLONE_PARENT,
              ont été indiqués, seuls ou ensemble, dans le masque flags.

       EINVAL (depuis Linux 2.6.32)
              CLONE_PARENT a été spécifié et l'appelant est un processus
              d'initialisation.

       EINVAL Renvoyée par l'enveloppe glibc de clone() quand fn ou stack valent
              NULL.

       EINVAL CLONE_NEWIPC a été spécifié dans le masque flags, mais le noyau
              n'a pas été configuré avec les options CONFIG_SYSVIPC et
              CONFIG_IPC_NS.

       EINVAL CLONE_NEWNET a été spécifié dans le masque flags, mais le noyau
              n'a pas été configuré avec l'option CONFIG_NET_NS.

       EINVAL CLONE_NEWPID a été spécifié dans le masque flags, mais le noyau
              n'a pas été configuré avec l'option CONFIG_PID_NS.

       EINVAL CLONE_NEWUSER a été spécifié dans le masque flags, mais le noyau
              n'a pas été configuré avec l'option CONFIG_USER_NS.

       EINVAL CLONE_NEWUTS a été spécifié dans le masque flags, mais le noyau
              n'a pas été configuré avec l'option CONFIG_UTS_NS.

       EINVAL stack n'est pas alignée sur une limite adaptée à cette
              architecture. Par exemple, sur arch64, stack doit être un multiple
              de 16.

       EINVAL (clone3() seulement)
              CLONE_DETACHED a été spécifié dans le masque flags.

       EINVAL (clone() seulement)
              CLONE_PIDFD a été indiqué avec CLONE_DETACHED dans le masque
              flags.

       EINVAL CLONE_PIDFD a été indiqué avec CLONE_THREAD dans le masque flags.

       EINVAL (clone() seulement)
              CLONE_PIDFD a été indiqué avec CLONE_PARENT_SETTID dans le masque
              flags.

       EINVAL (clone3() seulement)
              set_tid_size est supérieur au nombre de niveaux dans l'espace de
              noms du PID.

       EINVAL (clone3() seulement)
              Un des PID indiqué dans set_tid n'était pas valable.

       EINVAL (AArch64 seulement, Linux 4.6 et antérieur)
              stack n'était pas aligné sur une limite de 126 bits.

       ENOMEM Pas assez de mémoire pour copier les parties du contexte du
              processus appelant qui doivent être dupliquées, ou pour allouer
              une structure de tâche pour le processus enfant.

       ENOSPC (depuis Linux 3.7)
              CLONE_NEWPID a été spécifié dans le masque flags, et l'appel
              provoquerait un dépassement de la limite du nombre maximal
              d'espaces de noms utilisateur imbriqués. Consultez
              pid_namespaces(7).

       ENOSPC (depuis Linux 4.9 ; auparavant EUSERS)
              CLONE_NEWUSER a été spécifié dans le masque flags, et l'appel
              provoquerait un dépassement de la limite du nombre maximal
              d'espaces de noms utilisateur imbriqués. Consultez
              user_namespaces(7).

              De Linux 3.11 à Linux 4.8, l'erreur indiquée dans ce cas était
              EUSERS.

       ENOSPC (depuis Linux 4.9)
              Une des valeurs dans le masque flags indiquait de créer un nouvel
              espace de noms utilisateur, mais cela aurait provoqué un
              dépassement de la limite définie par le fichier correspondant dans
              /proc/sys/user. Pour plus de détails, voir namespaces(7).

       EOPNOTSUPP (clone3() seulement)
              CLONE_INTO_CGROUP était indiqué dans cl_args.flags, mais le
              descripteur de fichier indiqué dans cl_args.cgroup se rapporte à
              un cgroup version 2 dont l'état est domain invalid.

       EPERM  CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS,
              CLONE_NEWPID, ou CLONE_NEWUTS a été spécifié par un processus non
              privilégié (processus sans CAP_SYS_ADMIN).

       EPERM  CLONE_PID a été spécifié par un processus autre que le processus 0
              (cette erreur n'arrive que sur Linux 2.5.15 et antérieurs).

       EPERM  CLONE_NEWUSER a été spécifié dans le masque flags, mais
              l'identifiant utilisateur effectif ou l'identifiant de groupe
              effectif de l'appelant n'a pas de correspondance dans l'espace de
              noms parent (consultez user_namespaces(7)).

       EPERM (depuis Linux 3.9)
              CLONE_NEWUSER a été spécifié dans le masque flags et l'appelant se
              trouve dans un environnement chroot (c'est-à-dire que le
              répertoire racine de l'appelant ne correspond pas au répertoire
              racine de l'espace de noms montage dans lequel il se trouve).

       EPERM (clone3() seulement)
              set_tid_size était supérieur à zéro et l'appelant n'a pas la
              possibilité CAP_SYS_ADMIN dans un ou plusieurs des espaces de noms
              utilisateur qui appartiennent aux espaces de noms PID
              correspondants.

       ERESTARTNOINTR (depuis Linux 2.6.17)
              L'appel système a été interrompu par un signal et va être
              redémarré (cela n'est visible qu'à l'occasion d'un trace()).

       EUSERS (Linux 3.11 à Linux 4.8)
              CLONE_NEWUSER a été spécifié dans le masque flags, et l'appel
              provoquerait un dépassement de la limite du nombre maximal
              d'espaces de noms utilisateur imbriqués. Voir le point sur
              l'erreur ENOSPC ci-dessus.

VERSIONS
       L'appel système clone3() est apparu pour la première fois dans Linux 5.3.

CONFORMITÉ
       Ces appels système sont spécifiques à Linux et ne doivent pas être
       utilisés dans des programmes conçus pour être portables.

NOTES
       Une utilisation de ces appels systèmes consiste à implémenter des
       threads : un programme est scindé en plusieurs lignes de contrôle,
       s'exécutant simultanément dans un espace mémoire partagée.

       La glibc ne fournit pas d'enveloppe pour clone3() ; appelez-la en
       utilisant syscall(2).

       Remarquez que la fonction enveloppe clone() de la glibc effectue des
       changements dans la mémoire vers laquelle pointe stack (ce sont des
       changements nécessaires pour positionner correctement la pile pour
       l'enfant) avant de recourir à l'appel système clone(). Dès lors, lorsque
       clone() est utilisé pour créer des enfants de manière récursive,
       n'utilisez pas le tampon servant à la pile du parent en tant que pile de
       l'enfant.

       L'appel système  kcmp(2) peut être utilisé pour vérifier si deux
       processus partagent des ressources, telles qu'une table de descripteurs
       de fichier, des opérations Annuler de sémaphore sur System V ou un espace
       d'adressage virtuel.

       Les gestionnaires enregistrés en utilisant pthread_atfork(3) ne sont pas
       exécutés pendant un appel clone.

       Dans les noyaux 2.4.x, CLONE_THREAD ne fait en général pas du processus
       parent du nouveau thread un processus identique au parent du processus
       appelant. Cependant, pour les versions 2.4.7 à 2.4.18 du noyau,
       l'attribut CLONE_THREAD impliquait CLONE_PARENT (de même qu'avec les
       noyaux 2.6.0 et supérieurs).

       Sur i386, clone() ne devrait pas être appelé via vsyscall, mais
       directement en utilisant int $0x80.

   différences entre bibliothèque C et noyau
       L'appel système clone brut ressemble plus à fork(2), en ceci que
       l'exécution dans le processus enfant continue à partir du point d'appel.
       À ce titre, les arguments fn et arg de la fonction enveloppe de clone()
       sont omis.

       Contrairement à l'enveloppe de la glibc, l'appel système brut clone()
       accepte NULL en paramètre de stack (et de même, clone3() permet à
       cl_args.stack d'être NULL). Dans ce cas l'enfant utilise une copie de la
       pile du parent (la sémantique de copie-en-écriture assure que l'enfant
       recevra une copie indépendante des pages de la pile dès qu'un des deux
       processus la modifiera). Pour que cela fonctionne, il faut naturellement
       que CLONE_VM ne soit pas présent (si l'enfant partage la mémoire du
       parent du fait d'une utilisation de CLONE_VM, aucune duplication via la
       copie-en-écriture ne se produit et il peut s'ensuivre probablement un
       grand chaos).

       L'ordre des paramètres change aussi dans l'appel système brut et des
       variations existent dans les paramètres en fonction des architectures,
       comme indiqué dans les paragraphes suivants.

       L'interface de l'appel système brut sur des architectures x86-64 et
       quelques autres (dont sh, tile et alpha), est :

           long clone(unsigned long flags, void *stack,
                      int *parent_tid, int *child_tid,
                      unsigned long tls);

       Sur x86-32 et d'autres architectures classiques (dont score, ARM, ARM 64,
       PA-RISC, arc, Power PC, xtensa et MIPS), l'ordre des deux derniers
       paramètres est inversé :

           long clone(unsigned long flags, void *stack,
                     int *parent_tid, unsigned long tls,
                     int *child_tid);

       Sur les architectures cris et s390, l'ordre des deux premiers paramètres
       est inversé :

           long clone(void *stack, unsigned long flags,
                      int *parent_tid, int *child_tid,
                      unsigned long tls);

       Sur l'architecture microblaze, il existe un paramètre supplémentaire :

           long clone(unsigned long flags, void *stack,
                      int stack_size,         /* Taille de la pile */
                      int *parent_tid, int *child_tid,
                      unsigned long tls);

   blackfin, m68k, et sparc
       Les conventions de passage des arguments sur blackfin, m68k et sparc sont
       différentes de celles décrites précédemment. Pour plus de détails, se
       référer aux sources du noyau (et de la glibc).

   ia64
       Sur ia64, une interface différente est utilisée :

           int __clone2(int (*fn)(void *),
                        void *stack_base, size_t stack_size,
                        int flags, void *arg, ...
                     /* pid_t *parent_tid, struct user_desc *tls,
                        pid_t *child_tid */ );

       Le prototype présenté ci-dessus vaut pour la fonction enveloppe de la
       glibc ; pour l'appel système lui-même, il peut être décrit comme suit (il
       est identique au prototype clone() sur microblaze) :

           long clone2(unsigned long flags, void *stack_base,
                       int stack_size,         /* Taille de la pile */
                       int *parent_tid, int *child_tid,
                       unsigned long tls);

       __clone2() fonctionne comme clone(), sauf que stack_base pointe sur la
       plus petite adresse de la pile de l'enfant et que stack_size indique la
       taille de la pile sur laquelle pointe stack_base.

   Linux 2.4 et antérieurs
       Sous Linux 2.4 et plus anciens, clone() ne prend pas les paramètres
       parent_tid, tls, et child_tid.

BOGUES
       Les versions de la bibliothèque C GNU jusqu'à la 2.24 comprise
       contenaient une fonction enveloppe pour getpid(2) qui effectuait un cache
       des PID. Ce cache nécessitait une prise en charge par l'enveloppe de
       clone() de la glibc, mais des limites dans l'implémentation faisaient que
       le cache pouvait ne pas être à jour sous certaines circonstances. En
       particulier, si un signal était distribué à un enfant juste après l'appel
       à clone(), alors un appel à getpid(2) dans le gestionnaire de signaux du
       signal pouvait renvoyer le PID du processus appelant (le parent), si
       l'enveloppe de clone n'avait toujours pas eu le temps de mettre le cache
       de PID à jour pour l'enfant. (Ce point ignore le cas où l'enfant a été
       créé en utilisant CLONE_THREAD, quand getpid(2) doit renvoyer la même
       valeur pour l'enfant et pour le processus qui a appelé clone(), puisque
       l'appelant et l'enfant se trouvent dans le même groupe de threads. Ce
       problème de cache n'apparaît pas non plus si le paramètre flags contient
       CLONE_VM.) Pour obtenir la véritable valeur, il peut être nécessaire
       d'utiliser quelque chose comme ceci :

           #include <syscall.h>

           pid_t mypid;

           mypid = syscall(SYS_getpid);

       Suite à un problème de cache ancien, ainsi qu'à d'autres problèmes
       traités dans getpid(2), la fonctionnalité de mise en cache du PID a été
       supprimée de la glibc 2.25.

EXEMPLES
       Le programme suivant décrit l'usage de clone() dans le but de créer un
       processus enfant qui s'exécute dans un espace de noms UTS distinct. Le
       processus enfant change le nom d'hôte (hostname) dans son propre espace
       UTS. Les processus parent et enfant affichent chacun le nom d'hôte qui
       leur correspond, permettant ainsi de constater la différence des noms
       d'hôtes dans leurs espaces de noms UTS respectifs. Pour un exemple
       d’utilisation de ce programme, consultez setns(2).

       Dans le programme d'exemple, nous allouons la mémoire qui doit être
       utilisée pour la pile de l'enfant en utilisant mmap(2) au lieu de
       malloc(3) pour les raisons suivantes :

       *  mmap(2) alloue un bloc de mémoire commençant à la limite d'une page et
          multiple de la taille de la page. Cela est utile si on veut établir
          une page de protection (avec PROT_NONE) à la fin de la pile en
          utilisant mprotect(2).

       *  On peut indiquer l'attribut MAP_STACK pour demander une association
          adaptée à une pile. Pour le moment, cet attribut n'est pas
          opérationnel sur Linux, mais il existe et a des effets sur d'autres
          systèmes, donc on doit l'inclure pour la portabilité.

   Source du programme
       #define _GNU_SOURCE
       #include <sys/wait.h>
       #include <sys/utsname.h>
       #include <sched.h>
       #include <string.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <sys/mman.h>

       #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)

       static int              /* Commencer la fonction pour l'enfant cloné */
       childFunc(void *arg)
       {
           struct utsname uts;

           /* Modifier le nom d'hôte dans l'espace de noms UTS du
              processus enfant */

           if (sethostname(arg, strlen(arg)) == -1)
               errExit("sethostname");

           /* Récupérer et afficher le nom d'hôte */

           if (uname(&uts) == -1)
               errExit("uname");
           printf("uts.nodename dans l'enfant :  %s\n", uts.nodename);

           /* Rester en sommeil (fonction sleep) pour conserver l'espace
              de noms ouvert pendant un moment. Cela permet de réaliser
              quelques expérimentations — par exemple, un autre processus
              pourrait rejoindre l'espace de noms. */

           sleep(200);

           return 0;           /* Le processus enfant se termine à ce moment */
       }

       #define STACK_SIZE (1024 * 1024)    /* Taille de la pile pour
                                              l'enfant cloné */

       int
       main(int argc, char *argv[])
       {
           char *stack;                    /* Début du tampon de la pile */
           char *stackTop;                 /* Fin du tampon de la pile */
           pid_t pid;
           struct utsname uts;

           if (argc < 2) {
               fprintf(stderr, "Utilisation : %s <nom_d_hôte-enfant>\n", argv[0]);
               exit(EXIT_SUCCESS);
           }

           /* Allouer la mémoire à utiliser pour la pile du processus enfant */

           stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
           if (stack == MAP_FAILED)
               errExit("mmap");

           stackTop = stack + STACK_SIZE;  /* On suppose que la pile grandit vers
                                              le bas */

           /* Créer un processus enfant disposant de son propre
              espace de noms UTS ; le processus enfant débute
              son exécution dans childFunc() */

           pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
           if (pid == -1)
               errExit("clone");
           printf("clone() a renvoyé %ld\n", (long) pid);

           /* C'est ici que le processus parent échoue */

           sleep(1);           /* Laisser le temps au processus enfant de
                                  changer son nom d'hôte */

           /* Afficher le nom d'hôte pour l'espace de noms UTS du processus parent.
              Celui-ci sera différent du nom d'hôte pour l'espace de noms UTS du
              processus enfant. */

           if (uname(&uts) == -1)
               errExit("uname");
           printf("uts.nodename dans le parent : %s\n", uts.nodename);

           if (waitpid(pid, NULL, 0) == -1)    /* Attendre le processus enfant */
               errExit("waitpid");
           printf("Fin du processus enfant\n");

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI
       fork(2), futex(2), getpid(2), gettid(2), kcmp(2), mmap(2), pidfd_open(2),
       set_thread_area(2), set_tid_address(2), setns(2), tkill(2), unshare(2),
       wait(2), capabilities(7), namespaces(7), pthreads(7)

COLOPHON
       Cette page fait partie de la publication 5.08 du projet man-pages Linux.
       Une description du projet et des instructions pour signaler des anomalies
       et la dernière version de cette page, peuvent être trouvées à l'adresse
       https://www.kernel.org/doc/man-pages/.


TRADUCTION
       La traduction française de cette page de manuel a été créée par
       Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin
       <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>,
       François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe
       Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-
       luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas
       Huriaux <thomas.huriaux@gmail.com>, Nicolas François
       <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>,
       Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier
       <barbier@debian.org>, David Prévot <david@tilapin.org>, Cédric Boutillier
       <cedric.boutillier@gmail.com>, Frédéric Hantrais <fhantrais@gmail.com> et
       Jean-Philippe MENGUAL <jpmengual@debian.org>

       Cette traduction est une documentation libre ; veuillez vous reporter à
       la GNU General Public License version 3 concernant les conditions de
       copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si vous découvrez un bogue dans la traduction de cette page de manuel,
       veuillez envoyer un message à <debian-l10n-french@lists.debian.org>.



Linux                              9 juin 2020                          CLONE(2)