clone

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



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

SYNOPSIS
       /* Prototype de la fonction d'appel d'enrobage de glibc */

       #include <sched.h>

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

       /* Prototype de l'appel système brut */

       long clone(unsigned long flags, void *child_stack,
                 void *ptid, void *ctid,
                 struct pt_regs *regs);

   Conditions requises par la macro de test de fonctionnalités pour la
   fonction d'enrobage de glibc (consultez feature_test_macros(7)) :

       clone() :
           Ã partir de glibc 2.14 :
               _GNU_SOURCE
           Avant glibc 2.14 :
               _BSD_SOURCE || _SVID_SOURCE
                   /* _GNU_SOURCE est également suffisant */

DESCRIPTION
       clone() crée un nouveau processus, de façon analogue à fork(2).

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

       Contrairement à fork(2), clone() permet le partage d'une partie du
       contexte d'exécution entre le processus fils et le processus appelant.
       Le partage peut s'appliquer sur l'espace mémoire, sur la table des
       descripteurs de fichiers ou la table des gestionnaires de signaux.
       (Notez que sur cette page de manuel, le « processus appelant »
       correspond normalement au « processus père », mais voyez quand même
       la description de CLONE_PARENT plus bas).

       L'appel système clone() est principalement utilisé pour permettre
       l'implémentation des threads : un programme est scindé en plusieurs
       lignes de contrôle, s'exécutant simultanément dans un espace
       mémoire partagée.

       Quand le processus fils est créé par clone(), il exécute la fonction
       fn(arg). Ceci est différent de fork(2),  pour lequel l'exécution
       continue dans le processus fils à partir du moment de l'appel de
       fork(2). L'argument fn est un pointeur vers la fonction appelée par le
       processus fils lors de son démarrage. L'argument arg est transmis Ã
       la fonction fn lors de son invocation.

       Quand la fonction fn(arg) revient, le processus fils se termine. La
       valeur entière renvoyée par fn est utilisée comme code de retour du
       processus fils. 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 child_stack indique l'emplacement de la pile utilisée par
       le processus fils. Comme les processus fils et appelant peuvent
       partager de la mémoire, il n'est généralement pas possible pour le
       fils d'utiliser la même pile que son père. Le processus appelant doit
       donc préparer un espace mémoire pour stocker la pile de son fils, 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 child_stack doit pointer sur la plus haute
       adresse de l'espace mémoire prévu pour la pile du processus fils.

       L'octet de poids faible de flags contient le numéro du signal qui sera
       envoyé au père lorsque le processus fils se terminera. 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 du
       fils avec wait(2). Si aucun signal n'est indiqué, le processus parent
       ne sera pas notifié de la terminaison du fils.

       flags permet également de préciser ce qui sera partagé entre le
       père et le fils, en effectuant un OU binaire entre une ou plusieurs
       des constantes suivantes :

       CLONE_CHILD_CLEARTID (depuis Linux 2.5.49)
              Effacer l'ID du thread enfant à ctid dans la mémoire du fils
              lorsqu'il se termine, et réveiller 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 enfant à ctid dans la mémoire du
              fils.

       CLONE_FILES (depuis Linux 2.0)
              Si l'attribut CLONE_FILES est positionné, le processus appelant
              et le processus fils partagent la même table des 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 CLONE_FILES n'est pas positionné, le processus fils hérite
              d'une copie des descripteurs de fichier ouverts par l'appelant
              au moment de l'appel clone(). (Les copies des descripteurs de
              fichier dans le fils sont associées aux mêmes descriptions de
              fichiers ouverts (consultez open(2)) que les descripteurs de
              fichier correspondants dans le processus appelant.)  Les
              opérations effectuées ensuite sur un descripteur par un des
              processus n'affectent pas l'autre processus.

       CLONE_FS (depuis Linux 2.0)
              Si l'attribut CLONE_FS est positionné, le processus appelant et
              le processus fils partagent les mêmes informations concernant
              le système de fichiers. Ceci 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 choisi, le processus travaille sur une
              copie des informations de l'appelant concernant le système de
              fichiers. Cette copie est effectuée lors de l'invocation de
              clone(). Les appels à chroot(2), chdir(2), umask(2) effectués
              par un processus n'affectent pas l'autre processus.

       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ée-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_NEWIPC (depuis Linux 2.6.19)
              Si CLONE_NEWIPC est défini, alors créer le processus dans un
              nouvel espace de noms IPC. Si cet attribut n'est pas défini,
              alors (comme pour fork(2)) le processus est créé dans le même
              espace de noms IPC que le processus appelant. Cet attribut est
              sensé être utilisé pour l'implémentation de conteneurs.

              Un espace de noms IPC fournit une vue isolée des objets IPC en
              System V (consultez svipc(7)) et (Ã  partir de Linux 2.6.30) des
              files d'attente de messages POSIX (consultez mq_overview(7)). Le
              point commun entre ces mécanismes IPC est que les objets IPC y
              sont identifiés par d'autres moyens que des chemins d'accès
              dans des systèmes de fichiers.

              Les objets créés dans un espace de noms IPC sont visibles pour
              tous les processus qui sont membres de cet espace de noms, mais
              ne sont pas visibles pour les processus des autres espaces de
              noms IPC.

              Quand un espace de noms est détruit (c'est-à -dire, quand le
              dernier processus membre de cet espace de noms se termine), tous
              les objets IPC de cet espace de noms sont automatiquement
              détruits.

              Utiliser cet attribut nécessite : un noyau configuré avec les
              options CONFIG_SYSVIPC et CONFIG_IPC_NS et que le processus soit
              privilégié (CAP_SYS_ADMIN). Cet attribut ne peut pas être
              utilisé en même temps que 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 défini, alors créer le processus dans un
              nouvel espace de noms réseau. Si cet attribut n'est pas
              défini, alors (comme pour fork(2)) le processus est créé dans
              le même espace de noms réseau que le processus appelant. Cet
              attribut est sensé être utilisé pour l'implémentation de
              conteneurs.

              Un espace de noms réseau fournit une vue isolée de la pile
              réseau (interfaces des périphériques réseau, piles des
              protocoles IPv4 et IPv6, tables de routage, règles de pare-feu,
              les arbres de répertoire /proc/net et /sys/class/net, les
              sockets, etc.). Un périphérique réseau physique ne peut être
              que dans un seul espace de noms réseau. Une paire d'interface
              réseau virtuelle (« veth ») fournit une abstraction similaire
              à pipe qui peut être utilisé pour créer un pont vers une
              interface réseau physique d'un autre espace de noms réseau.

              Quand un espace de noms réseau est libéré (c'est-à -dire,
              quand le dernier processus de l'espace de noms se termine), ses
              périphériques réseau physiques sont remis dans l'espace de
              noms réseau initial (pas celui du processus père).

              Utiliser cet attribut nécessite : un noyau configuré avec
              l'option CONFIG_NET_NS et que le processus soit privilégié
              (CAP_SYS_ADMIN).

       CLONE_NEWNS (depuis Linux 2.4.19)
              Démarrer le processus dans un nouvel espace de noms de montage.

              Chaque processus se trouve dans un espace de noms de montage.
              Cet espace de noms du processus regroupe les données décrivant
              la hiérarchie des fichiers vus par le processus (l'ensemble des
              montages). Après un fork(2) ou clone() sans l'attribut
              CLONE_NEWNS le fils se déroule dans le même espace de noms de
              montage que son père. Les appels système mount(2) et umount(2)
              modifient l'espace de noms de montage du processus appelant, et
              affectent ainsi tous les processus se déroulant dans le même
              espace de noms, sans affecter les processus se trouvant dans
              d'autres espaces de noms de montage.

              Après un clone() avec l'attribut CLONE_NEWNS le fils cloné
              démarre dans un nouvel espace de noms de montage, initialisé
              avec une copie de l'espace de noms du père.

              Seul un processus privilégié (un processus ayant la capacité
              CAP_SYS_ADMIN) peut spécifier 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 défini, alors créer le processus dans un
              nouvel espace de noms de PID. Si cet attribut n'est pas défini,
              alors (comme pour fork(2)) le processus est créé dans le même
              espace de noms de PID que le processus appelant. Cet attribut
              est sensé être utilisé pour l'implémentation de conteneurs.

              Un espace de noms de PID fournit un environnement isolés pour
              les PID : les PID d'un nouvel espace de noms de PID commence Ã
              1, comme pour un système seul, et les appels à fork(2),
              vfork(2) et clone() produiront des processus avec des PID
              uniques dans l'espace de noms.

              Le premier processus créé dans un nouvel espace de noms
              (c'est-à -dire, le processus créé en utilisant l'attribut
              CLONE_NEWPID) a un PID de 1 et est le processus « init » pour
              l'espace de noms. Les fils qui deviennent orphelins dans cet
              espace de noms seront adoptés par ce processus plutôt que par
              init(8). Contrairement à l'init traditionnel, le processus
              « init » d'un espace de noms de PID peut se terminer et, s'il
              le fait, tous les processus dans l'espace de noms sont alors
              terminés.

              Les espaces de noms de PID forment une hiérarchie. Quand un
              espace de noms de PID est créé, les processus de cet espace de
              noms sont visibles depuis l'espace de noms de PID du processus
              qui a créé le nouvel espace de noms ; de la même façon, si
              l'espace de noms parent est lui-même le fils d'un autre espace
              de noms de PID, alors les processus du fils et du père seront
              tous visibles de l'espace de noms grand-père. à l'inverse, les
              processus de l'espace de noms de PID fils ne voient pas les
              processus de l'espace de noms parent. L'existence d'une
              hiérarchie d'espaces de noms signifie que chaque processus peut
              désormais avoir plusieurs PID : un par espace de noms dans
              lequel il est visible ; chacun de ces PID est unique dans les
              espaces de noms correspondants. (Un appel à getpid(2) renvoie
              toujours le PID associé à l'espace de noms dans lequel le
              processus se trouve.)

              Après avoir créé un nouvel espace de noms, il est utile pour
              le fils de changer son répertoire racine et monter une nouvelle
              instance de procfs dans /proc de telle sorte que des outils
              comme ps(1) fonctionnent correctement. (Si CLONE_NEWNS est
              également présent dans flags, alors il n'est pas nécessaire
              de changer de répertorie racine : une nouvelle instance de
              procfs peut être monté directement dans /proc.)

              L'utilisation de cet attribut nécessite : un noyau configuré
              avec l'option CONFIG_PID_NS et que le processus soit
              privilégié (CAP_SYS_ADMIN). Cet attribut ne peut pas être
              utilisé en même temps que CLONE_THREAD.

       CLONE_NEWUTS (depuis Linux 2.6.19)
              Si CLONE_NEWUTS est défini, alors créer le processus dans un
              nouvel espace de noms de 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. Cet attribut est
              sensé être utilisé pour l'implémentation de conteneurs.

              Un espace de noms UTS est l'ensemble des identifiants renvoyés
              par uname(2) ; parmi lesquels le nom de domaine et le nom
              d'hôte peuvent être modifiés respectivement à l'aide de
              setdomainname(2) et sethostname(2). Les modifications apportés
              Ã  ces identifiants dans un espace de noms UTS sont visibles par
              tous les processus du même espace de noms, mais ne sont pas
              visibles des processus des autres espaces de noms UTS.

              L'utilisation de cet attribut nécessite : un noyau configuré
              avec l'option CONFIG_UTS_NS et que le processus soit
              privilégié (CAP_SYS_ADMIN).

       CLONE_PARENT (depuis Linux 2.3.12)
              Si CLONE_PARENT est présent, le père du nouveau fils (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
              père du processus fils sera le processus appelant.

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

       CLONE_PARENT_SETTID (depuis Linux 2.5.49)
              Enregistrer l'ID du thread enfant à ptid dans la mémoire du
              père et du fils. (Dans Linux 2.5.32-2.5.48 il y a un attribut
              CLONE_SETTID qui fait cela.)

       CLONE_PID (obsolète)
              Si l'attribut CLONE_PID est positionné, les processus appelant
              et fils ont le même numéro de processus. C'est bien pour
              hacker le système, mais autrement il n'est plus utilisé.
              Depuis 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.

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

       CLONE_SETTLS (depuis Linux 2.5.32)
              Le paramètre newtls est le nouveau descripteur TLS (Thread
              Local Storage). (Consultez set_thread_area(2).)

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

              Si CLONE_SIGHAND n'est pas utilisé, le processus fils 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-test6, l'attribut CLONE_VM doit également
              être spécifié dans flags si CLONE_SIGHAND l'est.

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

              Cet attribut est marqué comme obsolète depuis Linux 2.6.25, et
              a été complètement supprimé dans Linux 2.6.38.

       CLONE_SYSVSEM (depuis Linux 2.5.10)
              Si CLONE_SYSVSEM est positionné, le fils et le processus
              appelant partagent la même liste de compteurs « undo » pour
              les sémaphores System V (consultez semop(2)). Si cet attribut
              n'est pas utilisé, le fils a une liste « undo » séparée,
              initialement vide.

       CLONE_THREAD (depuis Linux 2.4.0-test8)
              Si CLONE_THREAD est présent, le fils 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ées 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 père 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 ê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 fils avec fork(2),
              n'importe lequel des threads du groupe peut utiliser wait(2) sur
              ce fils.

              Depuis Linux 2.5.35, l'attribut CLONE_SIGHAND de flags doit
              être positionné si CLONE_THREAD l'est. Depuis
              Linux 2.6.0-test6, CLONE_SIGHAND a également besoin de
              CLONE_THREAD.

              Un signal peut être envoyé à un groupe de threads dans son
              ensemble (c'est‐à ‐dire à  un TGID) avec kill(2), ou bien à  un
              thread en particulier (Ã  un TID) avec tgkill(2).

              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 signaux, défini par
              sigprocmask(2), mais les signaux peuvent être en attente soit
              pour le processus dans son ensemble (donc peut être reçu par
              n'importe lequel des threads du groupe), quand ils sont envoyés
              avec kill(2), soit pour un thread particulier, lorsqu'ils sont
              envoyés par tgkill(2). Un appel à sigpending(2) renvoie un
              ensemble de signaux qui est l'union des processus en attente
              pour le processus et ceux en attente pour le thread appelant.

              Si kill(2) est utilisé pour envoyer un signal à 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 délivrer le signal envoyé par kill(2).

       CLONE_UNTRACED (depuis Linux 2.5.46)
              Si l'attribut CLONE_UNTRACED est positionné, alors un processus
              traçant le père ne peut pas forcer CLONE_PTRACE pour ce fils.

       CLONE_VFORK (depuis Linux 2.2)
              Si le bit CLONE_VFORK est actif, l'exécution du processus
              appelant est suspendue jusqu'à ce que le fils 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
              doit pas considérer que l'ordre d'exécution soit déterminé.

       CLONE_VM (depuis Linux 2.0)
              Si le bit CLONE_VM est actif, le processus appelant et le
              processus fils 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ées
              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 fils utilisera une
              copie distincte de l'espace mémoire de l'appelant. Le cliché
              est réalisé lors de l'invocation de clone(). Les écritures ou
              les projections de fichiers en mémoire effectuées par un
              processus n'affectent pas l'autre processus, comme cela se passe
              avec fork(2).

   L'interface de l'appel système brut
       L'appel système clone ressemble plus à fork(2), en ceci que
       l'exécution dans le processus fils continue à partir du point
       d'appel. Ã ce titre, les arguments fn et arg de la fonction d'enrobage
       de clone() sont omis. De plus, l'ordre des arguments change.
       L'interface de l'appel système brut sur x86 et sur plusieurs autres
       architectures est à peu près :

           long clone(unsigned long flags, void *child_stack,
                      void * ptid, void *ctid,
                      struct pt_regs *regs);

       Une autre différence : pour l'appel système brut, l'argument
       child_stack peut être nul, puisque la sémantique de
       copie-en-écriture assure que le fils 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.

       Pour certaines architectures, l'ordre des arguments de l'appel système
       diffère de ce qui est décrit ci-dessus. Sur les architectures score,
       microblaze, ARM, ARM 64, PA-RISC, arc, Power PC, xtensa, et MIPS,
       l'ordre des quatrième et cinquième arguments est inversé. Sur les
       architectures cris et s390, l'ordre des premier et deuxième arguments
       est inversé.

   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 glibc).

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

       int __clone2(int (*fn)(void *),
                    void *child_stack_base, size_t stack_size,
                    int flags, void *arg, ...
                 /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

       Le prototype présenté plus haut correspond à la fonction
       intermédiaire de glibc ; l'interface de l'appel système brut ne
       reconnaît pas les arguments fn ou arg, et modifie l'ordre des
       arguments, de sorte que  flags devient le premier argument, et tls le
       dernier.

       __clone2() fonctionne comme clone(), aux différences suivantes près :
       child_stack_base pointe sur la plus petite adresse de la pile du fils,
       et stack_size indique la taille de la pile sur laquelle pointe
       child_stack_base.

   Linux 2.4 et antérieurs
       Sous Linux 2.4 et plus anciens, clone() ne prend pas les arguments
       ptid, tls et ctid.

VALEUR RENVOYÃE
       En cas de réussite, le TID du processus fils 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 fils n'est créé, et errno
       contiendra le code d'erreur.

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

       EINVAL CLONE_SIGHAND a été spécifié mais pas CLONE_VM (depuis Linux
              2.6.0-test6).

       EINVAL CLONE_THREAD a été spécifié mais pas CLONE_SIGHAND  (depuis
              Linux 2.5.35).

       EINVAL Les attributs CLONE_NEWNS et CLONE_FS ont été indiqués
              simultanément dans flags.

       EINVAL Les attributs CLONE_NEWIPC et CLONE_SYSVSEM ont été indiqués
              simultanément dans flags.

       EINVAL Les attributs CLONE_NEWPID et CLONE_THREAD ont été indiqués
              simultanément dans flags.

       EINVAL Renvoyée par clone() quand une valeur nulle a été indiquée
              pour le paramètre child_stack.

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

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

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

       EINVAL CLONE_NEWUTS a été indiqué dans flags, mais le noyau n'a pas
              été configuré avec l'option CONFIG_UTS.

       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 fils.

       EPERM  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é réclamé par un processus autre que le
              processus 0.

VERSIONS
       Il n'y a pas de définition pour clone() dans la libc5. glibc2 fournit
       une définition de clone() comme décrit ici.

CONFORMITÃ
       clone() est spécifique à Linux et ne doit pas être utilisé dans des
       programmes conçus pour être portables.

NOTES
       Dans les noyaux 2.4.x, CLONE_THREAD ne rend pas en général le
       processus père de l'appelant père du nouveau thread. 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).

       CLONE_DETACHED a existé pendant un moment (introduit dans 2.5.32): le
       père ne veut pas de signal à la mort du fils. Dans 2.6.2, la
       nécessité d'utiliser ce paramètre avec CLONE_THREAD a été
       supprimée. Cet attribut est toujours défini, mais n'a plus aucun
       effet.

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

BOGUES
       Les versions de la bibliothèque C GNU qui gèrent la bibliothèque de
       gestion des threads NPTL contiennent une fonction enveloppe pour
       getpid(2) qui effectue un cache des PID. Ce cache nécessite une prise
       en charge par l'enveloppe de clone() de la glibc, mais telle qu'il est
       actuellement implémenté, le cache peut ne pas être à jour sous
       certaines circonstances. En particulier, si un signal est distribué Ã
       un fils juste après l'appel à clone(), alors un appel à getpid(2)
       dans le gestionnaire de signaux du signal peut renvoyer le PID du
       processus appelant (le père), si l'enveloppe de clone n'a toujours pas
       eu le temps de mettre le cache de PID Ã  jour pour le fils. (Cette
       discussion ignore le cas où le fils a été créé en utilisant
       CLONE_THREAD, quand getpid(2) doit renvoyer la même valeur pour le
       fils et pour le processus qui a appelé clone(), puisque l'appelant et
       le fils 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);

EXEMPLE
       Le programme suivant décrit l'usage de clone() dans le but de créer
       un processus fils qui s'exécute dans un espace de noms UTS distinct.
       Le processus fils change le nom d'hôte (hostname) dans son propre
       espace UTS. Les processus père et fils 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.

   Code 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>

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

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

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

           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 le fils : %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 fils se termine à ce moment */
       }

       #define STACK_SIZE (1024 * 1024)    /* Taille de la pile pour le
                                              fils 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-fils>\n", argv[0]);
               exit(EXIT_SUCCESS);
           }

           /* Allouer la pile pour le processus fils */

           stack = malloc(STACK_SIZE);
           if (stack == NULL)
               errExit("malloc");
           stackTop = stack + STACK_SIZE;  /* Pile supposée s'étendre vers
                                              le bas */

           /* Créer un processus fils disposant de son propre
              espace de noms UTS ; le processus fils 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 père échoue */

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

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

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

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

           exit(EXIT_SUCCESS);
       }

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

COLOPHON
       Cette page fait partie de la publication 3.70 du projet man-pages
       Linux. Une description du projet et des instructions pour signaler des
       anomalies peuvent être trouvées à l'adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION
       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
       <http://po4a.alioth.debian.org/> par l'équipe de traduction
       francophone au sein du projet perkamon
       <http://perkamon.alioth.debian.org/>.

       Christophe Blaess <http://www.blaess.fr/christophe/> (1996-2003), Alain
       Portal <http://manpagesfr.free.fr/> (2003-2006).  Julien Cristau et
       l'équipe francophone de traduction de Debian (2006-2009).

       Veuillez signaler toute erreur de traduction en écrivant Ã
       <perkamon-fr@traduc.org>.

       Vous pouvez toujours avoir accès à la version anglaise de ce document
       en utilisant la commande « LC_ALL=C man <section> <page_de_man> ».



Linux                             28 mai 2014                         CLONE(2)