CLONE

Section : Manuel du programmeur Linux (2)
Mise à jour de la version anglaise : 13 avril 2008
Index Menu principal  

NOM

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

SYNOPSIS

#define _GNU_SOURCE
#include <sched.h>

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

DESCRIPTION

clone() crée un nouveau processus, exactement comme le fait fork(2). C'est en fait une fonction de bibliothèque s'appuyant sur l'appel système clone() sous-jacent, référencé dans la suite de ce document par sys_clone. Une description de sys_clone se trouve plus bas sur cette page.

Contrairement à fork(2), cette routine 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 fichier 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éé, avec clone(), il exécute la fonction fn(arg) de l'application. (Ceci est différent de fork(2) avec lequel l'exécution continue dans le fils au point de l'appel fork(2)) L'argument fn est un pointeur sur 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 pile_fils 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 pile_fils 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 de terminaison 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 zéro ou plusieurs des constantes suivantes :

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_FS
Si l'attribut CLONE_FS est positionné, les processus appelant et 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_FILES
Si l'attribut CLONE_FILES est positionné, les processus appelant et fils partagent la même table des descripteurs de fichier. Tout descripteur de fichier créé par le processus appelant ou par le processus fils est également valide dans l'autre processus. De la même manière, si l'un des processus ferme un descripteur de fichier ou modifie ses attributs associés (en utilisant l'opération F_SETFD de fcntl(2)), l'autre processus 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 font référence aux mêmes descriptions de fichier ouverts (voir open(2)) que les descripteurs de fichier correspondants dans le processus appelant.) Les opérations ultérieures qui ouvrent ou ferment les descripteurs de fichier, ou modifient les attributs des descripteurs de fichier, effectuées soit par le processus appelant soit par le processus fils, n'affectent pas l'autre processus.

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

Chaque processus se trouve dans un espace de noms. 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 nom que son père. Les appels système mount(2) et umount(2) modifient l'espace de noms du processus appelant, et affectent ainsi tous les processus se déroulant dans le même espace, sans affecter les processus se trouvant dans d'autres espaces.

Après un clone() avec l'attribut CLONE_NEWNS le fils cloné démarre dans un nouvel espace de noms, initialisé avec une copie de l'espace 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_SIGHAND
Si l'attribut CLONE_SIGHAND est positionné, les processus appelant et 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 être spécifié dans si CLONE_SIGHAND l'est.

CLONE_PTRACE
Si l'attribut CLONE_PTRACE est positionné et si l'appelant est suivi par un débogueur, alors le fils sera également suivi (voir ptrace(2)).
CLONE_UNTRACED (depuis Linux 2.5.46)
Si l'attribut CLONE_UNTRACED est positionné, un processus tracé ne peut pas forcer CLONE_PTRACE sur son processus fils.
CLONE_STOPPED (depuis Linux 2.6.0-test2)
Si l'attribut CLONE_STOPPED est positionné, le fils est stoppé (comme s'il avait le signal SIGSTOP), et doit être relancer en lui envoyant le signal SIGCONT. Depuis Linux 2.6.25, cet attribut est déconseillé. Vous avez probablement jamais voulu l'utiliser, vous ne devriez certainement pas l'utiliser, et bientôt, il sera supprimé.
CLONE_VFORK
Si l'attribut CLONE_VFORK est positionné, 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
Si le bit CLONE_VM est actif, les processus père et 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é étant 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).

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_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. Pour rendre la suite de la discussion sur CLONE_THREAD plus lisible, le terme « thread » est utilisé pour faire référence au processus d'un groupe de threads.

Les groupes de threads sont une fonctionnalité ajoutée dans Linux 2.4 pour gérer la notion POSIX de threads d'un ensemble de threads qui partagent un même PID. De manière interne, ce PID partagé est ainsi appelé identifiant de groupe de threads (TGID) pour le groupe de threads. Depuis Linux 2.4, les appels à getpid(2) renvoient le TGID de l'appelant.

Les threads dans un groupe peuvent être différenciés par (à l'échelle du système) leur identifiant de thread unique (TID). Un nouveau TID est disponible comme le résultat d'une fonction renvoyé à l'appelant de clone(), et un thread peut obtenir son propre TID en utilisant gettid(2).

Lorsqu'un appel à clone() est effectué sans spécifier CLONE_THREAD, le thread résultant est placé dans un nouveau groupe de threads dont le TGID est identique au TID du thread. Ce thread est le leader de ce nouveau groupe de threads.

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

Après que tous les threads d'un groupe de threads se terminent, un signal SIGCHLD (ou tout autre signal de terminaison) est envoyé au processus parent du groupe de threads.

Si l'un des threads dans un groupe de threads effectue un execve(2), tous les threads autres que le leader du groupe se terminent, et le nouveau programme s'exécute dans le leader du groupe de threads.

Si l'un des threads d'un groupe de threads crée un fils avec fork(2), n'importe lequel des threads du groupe peut attendre (wait(2)) ce fils.

Depuis Linux 2.5.35, flags doit inclure CLONE_SIGHAND si CLONE_THREAD est spécifié.

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

Les dispositions et actions des signaux sont à l'échelle du système : si un signal non géré est délivré à un thread, cela affectera (terminaison, stop, continuation, ignoré) tous les membres du groupe de threads.

Chaque thread a son propre masque de signaux, configuré avec sigprocmask(2), mais les signaux peuvent être en attente soit pour le processus dans son ensemble (c'est-à-dire pour chaque membre du groupe de threads), lorsqu'ils sont envoyés par 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 signaux en attente pour le processus entier et des signaux en attente pour le thread appelant.

Si kill(2) est utilisé pour envoyer un signal à un groupe de threads et que ce groupe a installé un gestionnaire pour ce signal, le gestionnaire sera invoqué dans exactement un des membres du groupe de threads, arbitrairement sélectionné, parmi ceux qui n'ont pas bloqué le signal. Si plusieurs threads dans un groupe sont en attente du même signal en utilisant sigwaitinfo(2), le noyau en sélectionnera arbitrairement un pour recevoir le signal envoyé avec kill(2).

CLONE_SYSVSEM (depuis Linux 2.5.10)
Si l'attribut CLONE_SYSVSEM est positionné, le processus fils et le processus appelant partagent la même liste de valeurs « undo » de sémaphores System V (voir semop(2)). Si cet attribut n'est pas positionné, le fils a une liste « undo » séparée qui est initialement vide.
CLONE_SETTLS (depuis Linux 2.5.32)
Le paramètre newtls est le nouveau descripteur TLS (Thread Local Storage). (Voir set_thread_area(2).)
CLONE_PARENT_SETTID (depuis Linux 2.5.49)
Enregistrer l'ID du thread enfant à parent_tidptr 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_CHILD_SETTID (depuis Linux 2.5.49)
Enregistrer l'ID du thread enfant à child_tidptr dans la mémoire du fils.
CLONE_CHILD_CLEARTID (depuis Linux 2.5.49)
Effacer l'ID du thread enfant à child_tidptr 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.
 

sys_clone

L'appel système sys_clone ressemble plus à fork(2), en ceci que l'exécution dans le processus fils continue à partir du point d'appel. Ainsi sys_clone ne nécessite que les arguments flags et pile_fils qui ont la même signification que pour clone(). (Notez que l'ordre de ces arguments est différent de celui dans clone().)

Une autre différence : pour sys_clone, l'argument pile_fils 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.

Depuis Linux 2.5.49, l'appel système a cinq paramètres. Les deux nouveaux paramètres sont parent_tidptr qui pointe à l'endroit (dans la mémoire du père et celle du fils) où l'ID du thread fils sera écrit au cas où CLONE_PARENT_SETTID serait spécifié, et child_tidptr qui pointe à l'endroit (dans la mémoire du fils) où l'ID du thread fils sera écrit au cas où CLONE_CHILD_SETTID serait spécifié.  

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.
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
Renvoyée par clone () quand une valeur nulle a été indiquée pour le paramètre pile_fils.
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_NEWNS a été spécifié par un processus non-root (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É

Les appels système clone() et sys_clone sont spécifiques à Linux et ne doivent pas être employés dans des programmes portables.  

NOTES

Dans les noyaux 2.4.x, CLONE_THREAD ne fait généralement pas le parent d'un nouveau thread identique au parent du processus appelant. Toutefois, pour les noyaux 2.4.7 à 2.4.18, l'attribut CLONE_THREAD entraîne l'attribut CLONE_PARENT (comme dans les noyaux 2.6). Pendant un certain temps, il y avait CLONE_DETACHED (introduit dans le 2.5.32) : le parent ne veut pas de signal indiquant la sortie du fils. Dans le noyau 2.6.2, la nécessité de fournir celui-ci avec CLONE_THREAD a disparu. Cet attribut existe toujours mais n'a aucun effet.

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

Sur IA-64, un appel système différent est utilisé :


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

L'appel système __clone2() opère de la même manière que clone(), excepté que child_stack_base pointe sur l'adresse la plus basse de la zone de pile du fils et que stack_size indique la taille de la pile pointée par child_stack_base.  

BOGUES

Les versions de la glibc qui incluent la bibliothèque de gestion des threads NPTL contiennent une fonction enveloppe pour getpid(2) qui cache les PID. Dans les programmes liés à de telles bibliothèques, les appels à getpid(2) peuvent renvoyer la même valeur, y compris pour des threads qui n'ont pas été créés en utilisant CLONE_THREAD (et ne sont donc pas dans le même groupe de threads). Pour connaître la vérité, il peut être nécessaire d'utiliser un code tel que :

    #include <syscall.h>

    pid_t mypid;

    mypid = syscall(SYS_getpid);
 

VOIR AUSSI

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

TRADUCTION

Ce document est une traduction réalisée par Christophe Blaess <http://www.blaess.fr/christophe/> le 14 octobre 1996, mise à jour par Alain Portal <aportal AT univ-montp2 DOT fr> le 15 juin 2006 et révisée le 17 juillet 2008.

L'équipe de traduction a fait le maximum pour réaliser une adaptation française de qualité. La version anglaise la plus à jour de ce document est toujours consultable via la commande : « LANG=C man 2 clone ». N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute erreur dans cette page de manuel.

 

Index

NOM
SYNOPSIS
DESCRIPTION
sys_clone
VALEUR RENVOYÉE
ERREURS
VERSIONS
CONFORMITÉ
NOTES
BOGUES
VOIR AUSSI
TRADUCTION

Dernière mise à jour : 17 juillet 2008