clone(2) System Calls Manual clone(2) NOM clone, __clone2, clone3 - Creer un processus enfant (child) BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS /* Prototype de la fonction enveloppe de la glibc */ #define _GNU_SOURCE #include int clone(int (*fn)(void *_Nullable), void *stack, int flags, void *_Nullable arg, ... /* pid_t *_Nullable parent_tid, void *_Nullable tls, pid_t *_Nullable child_tid */ ); /* Pour le prototype de l'appel systeme clone() brut, voir REMARQUES */ #include /* Definition de struct clone_args */ #include /* Definition des constantes CLONE_* */ #include /* Definition des constantes SYS_* */ #include long syscall(SYS_clone3, struct clone_args *cl_args, size_t size); Remarque : La glibc ne fournit pas d'enveloppe pour clone3() ; appelez-la en utilisant syscall(2). DESCRIPTION Ces appels systeme creent un nouveau processus << enfant >>, de facon analogue a fork(2). Contrairement a fork(2), ces appels systeme offrent un controle plus precis du contexte d'execution partage entre le processus appelant et son enfant. Par exemple, en utilisant ces appels systeme, l'appelant peut controler 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 systeme permettent egalement au nouveau processus enfant d'aller dans un namespaces(7) a 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 decrit les interfaces suivantes : - Cette page presente a la fois la fonction enveloppe clone() de la glibc et l'appel systeme sous-jacent sur lequel elle s'appuie. Le texte principal decrit la fonction enveloppe ; les differences avec l'appel systeme brut sont precisees vers la fin de cette page. - Le nouvel appel systeme clone3(). Dans la suite de cette page, le terme << appel clone >> est utilise pour evoquer les details applicables a toutes ces interfaces. La fonction enveloppe clone() Quand le processus enfant est cree par la fonction enveloppe clone(), il debute son execution par un appel a la fonction vers laquelle pointe l'argument fn (cela est different de fork(2), pour lequel l'execution continue dans le processus enfant a partir du moment de l'appel de fork(2)). L'argument arg est passe comme argument de la fonction fn. Quand la fonction fn(arg) renvoie, le processus enfant se termine. La valeur entiere renvoyee par fn est utilisee comme code de retour du processus enfant. Ce dernier peut egalement se terminer de maniere explicite en invoquant la fonction exit(2) ou apres la reception d'un signal fatal. L'argument stack indique l'emplacement de la pile utilisee par le processus enfant. Comme les processus enfant et appelant peuvent partager de la memoire, il n'est generalement pas possible pour l'enfant d'utiliser la meme pile que son parent. Le processus appelant doit donc preparer un espace memoire pour stocker la pile de son enfant, et transmettre a clone un pointeur sur cet emplacement. Les piles croissent vers le bas sur tous les processeurs implementant Linux (sauf le HP PA), donc stack doit pointer sur la plus haute adresse de l'espace memoire prevu 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 parametres restants de clone() sont decrits ci-dessous. clone3() L'appel systeme clone3() fournit un sur-ensemble de la fonctionnalite de l'ancienne interface de clone(). Il offre egalement un certain nombre d'ameliorations de l'API dont : un espace pour des bits d'attributs supplementaires, une separation plus propre dans l'utilisation de plusieurs parametres et la possibilite d'indiquer la taille de la zone de la pile de l'enfant. Comme avec fork(2), clone3() renvoie a la fois au parent et a l'enfant. Il renvoie 0 dans le processus enfant et il renvoie le PID de l'enfant dans le parent. Le parametre cl_args de clone3() est une structure ayant la forme suivante : struct clone_args { u64 flags; /* Masque de bit d'attribut */ u64 pidfd; /* Ou stocker le descripteur de fichier du PID (int *) */ u64 child_tid; /* Ou stocker le TID enfant, dans la memoire de l'enfant (pid_t *) */ u64 parent_tid; /* Ou stocker le TID enfant, dans la memoire du parent (pid_t *) */ u64 exit_signal; /* Signal a 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'elements dans set_tid (depuis Linux 5.5) */ u64 cgroup; /* Descripteur de fichier du cgroup cible de l'enfant (depuis Linux 5.7) */ }; Le parametre size fourni a clone3() doit etre initialise a la taille de cette structure (l'existence du parametre size autorise des extensions futures de la structure clone_args). La pile du processus enfant est indiquee 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 indique (voir ci-dessous), une pile doit etre explicitement allouee et indiquee. Sinon, ces deux champs peuvent valoir NULL et 0, ce qui amene l'enfant a utiliser la meme zone de pile que son parent (dans l'espace d'adressage virtuel de son propre enfant). Les autres champs du parametre cl_args sont abordes ci-dessous. Equivalence entre les parametres de clone() et de clone3() Contrairement a l'ancienne interface clone(), ou les parametres sont passes individuellement, ceux de la nouvelle interface clone3() sont empaquetes dans la structure clone_args presentee ci-dessus. Cette structure permet de passer un ensemble d'informations a l'aide des arguments de clone(). Le tableau suivant montre l'equivalence entre les parametres de clone() et les champs du parametre clone_args fournis a clone3() : clone() clone3() Notes Champ cl_args attributs & ~0xff attributs Pour la plupart des attributs, details 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 stack stack --- stack_size tls tls Voir CLONE_SETTLS --- set_tid Voir ci-dessous pour des details --- set_tid_size --- cgroup Voir CLONE_INTO_CGROUP Signal de fin de l'enfant Quand le processus enfant se termine, un signal peut etre envoye au parent. Le signal de fin est indique dans l'octet de poids faible de flags (clone()) ou dans cl_args.exit_signal (clone3()). Si ce signal est different de SIGCHLD, le processus parent doit egalement specifier les options __WALL ou __WCLONE lorsqu'il attend la fin de l'enfant avec wait(2). Si aucun signal n'est indique (donc zero), le processus parent ne sera pas notifie de la terminaison de l'enfant. Le tableau set_tid Par defaut, le noyau choisit le PID sequentiel suivant pour le nouveau processus dans chacun des espaces de noms de PID ou il est present. Lors de la creation d'un processus avec clone3(), le tableau set_tid (depuis Linux 5.5) peut etre utilise pour selectionner des PID specifiques pour le processus dans tout ou partie des espaces de noms ou il est present. Si le PID du processus nouvellement cree ne doit etre positionne que dans l'espace de noms du processus actuel ou dans celui du PID nouvellement cree (si flags contient CLONE_NEWPID), le premier element du tableau set_tid doit etre le PID souhaite et set_tid_size doit valoir 1. Si le PID du processus nouvellement cree doit avoir une certaine valeur dans plusieurs espaces de noms de PID, le tableau set_tid peut avoir plusieurs entrees. La premiere entree definit le PID de l'espace de noms le plus imbrique, puis chacune des entrees suivantes contient le PID de l'espace de noms superieur correspondant. Le nombre d'espaces de noms de PID ou un PID doit etre positionne est defini par set_tid_size, qui ne peut pas etre plus grand que le nombre d'espaces de noms de PID imbriques. Pour creer un processus dont les PID suivants s'inscrivent dans la hierarchie de l'espace de noms de PID : Niveau esp. noms du PID PID demande Notes 0 31496 Espace de noms du PID le plus a l'exterieur 1 42 2 7 Espace de noms du PID le plus a l'interieur 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 les plus a l'interieur doivent etre indiques, positionnez le tableau sur : set_tid[0] = 7; set_tid[1] = 42; set_tid_size = 2; Le PID dans les espaces de noms de PID en dehors des deux espaces de noms les plus a l'interieur sera selectionne de la meme maniere qu'on selectionne n'importe quel autre PID. La fonctionnalite set_tid exige CAP_SYS_ADMIN ou (depuis Linux 5.9) CAP_CHECKPOINT_RESTORE dans tous les espaces de noms appartenant a l'utilisateur des espaces de noms du processus cible. Les appelants ne peuvent choisir qu'un PID superieur a 1 dans un espace de noms de PID donne si un processus init (a savoir un processus dont le PID est 1) existe deja dans cet espace de noms. Sinon, l'entree 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 a l'appelant d'indiquer ce qui est partage entre le processus appelant et son enfant. Ce masque de bit - le parametre flags de clone() ou le champ cl_args.flags passe a clone3() - est designe comme le masque flags dans le reste de cette page. Le masque flags est indique comme un OU binaire de zero ou plus des constantes ci-dessous. Sauf explicitement indiques, ces attributs sont disponibles (et ont le meme effet) dans clone() et dans clone3(). CLONE_CHILD_CLEARTID (depuis Linux 2.5.49) Effacer (zero) l'ID du thread enfant situe la ou pointe child_tid (clone()) ou cl_args.child_tid (clone3()) dans la memoire de l'enfant lorsqu'il se termine, et provoquer le reveil avec le futex a cette adresse. L'adresse concernee peut etre modifiee par l'appel systeme set_tid_address(2). Cela est utilise dans les bibliotheques de gestion de threads. CLONE_CHILD_SETTID (depuis Linux 2.5.49) Enregistrer l'ID du thread de l'enfant la ou pointe child_tid ((clone()) ou cl_args.child_tid (clone3()) dans la memoire de l'enfant. L'operation d'enregistrement se termine avant que l'appel clone ne redonne le controle a l'espace utilisateur dans le processus enfant (remarquez que l'operation d'enregistrement peut ne pas etre terminee avant que l'appel clone ne renvoie au processus parent, ce qui sera pertinent si l'attribut CLONE_VM est egalement utilise). CLONE_CLEAR_SIGHAND (depuis Linux 5.5) Par defaut, l'etat des signaux du thread de l'enfant est le meme que celui du parent. Si cet attribut est positionne, tous les signaux geres par le parent (et non definis a SIG_IGN) sont reinitialises a leur etat par defaut (SIG_DFL) dans l'enfant. Indiquer cet attribut avec CLONE_SIGHAND n'a pas de sens et n'est pas autorise. CLONE_DETACHED (historique) Pendant un moment (pendant la serie de versions au cours du developpement 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 ete inhibe par l'attribut CLONE_THREAD et quand Linux 2.6.0 a ete publie, cet attribut n'avait pas d'effet. A partir de Linux 2.6.2, il n'a plus ete necessaire de fournir cet attribut avec CLONE_THREAD. Cet attribut est toujours defini, mais il est generalement ignore 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 positionne, le processus appelant et le processus enfant partagent la meme table de descripteurs de fichier. Tout descripteur cree par un processus est egalement valable pour l'autre processus. De meme si un processus ferme un descripteur, ou modifie ses attributs (en utilisant l'operation fcntl(2) F_SETFD), l'autre processus en est aussi affecte. Si un processus qui partage une table de descripteurs de fichier appelle execve(2), sa table est dupliquee (non partagee). Si CLONE_FILES n'est pas positionne, le processus enfant herite d'une copie des descripteurs de fichier ouverts par l'appelant au moment de l'appel clone(). Les operations d'ouverture et de fermeture ou de modification d'attributs du descripteur de fichier subsequentes, effectuees 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 associees aux memes descriptions de fichiers ouverts que les descripteurs de fichier correspondants dans le processus appelant, partageant ainsi les attributs de position et d'etats du fichier (consultez open(2)). CLONE_FS (depuis Linux 2.0) Si l'attribut CLONE_FS est positionne, le processus appelant et le processus enfant partagent les memes informations concernant le systeme de fichiers. Cela inclut la racine du systeme de fichiers, le repertoire de travail, et l'umask. Tout appel a chroot(2), chdir(2) ou umask(2) effectue par un processus aura egalement une influence sur l'autre processus. Si CLONE_FS n'est pas positionne, le processus enfant travaille sur une copie des informations de l'appelant concernant le systeme de fichiers au moment de l'appel clone. Les appels a chroot(2), chdir(2), umask(2) effectues ensuite par un processus n'affectent pas l'autre processus. CLONE_INTO_CGROUP (depuis Linux 5.7) Par defaut, un processus enfant est mis dans le meme cgroup version 2 que son parent. L'attribut CLONE_INTO_CGROUP permet au processus enfant d'etre cree dans un cgroup version 2 different (remarquez que CLONE_INTO_CGROUP n'a d'effet que sur les cgroup version 2). Pour mettre le processus enfant dans un cgroup different, l'appelant indique CLONE_INTO_CGROUP dans cl_args.flags et passe un descripteur de fichier qui se rapporte a un cgroup version 2 du champ cl_args.cgroup (le descripteur de fichier peut etre obtenu en ouvrant un repertoire cgroup v2, en utilisant l'attribut O_RDONLY ou O_PATH). Remarquez que toutes les restrictions habituelles (decrites 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 : - Creer un processus dans un autre cgroup que celui du parent permet au gestionnaire de service de placer directement de nouveaux services dans des cgroup dedies. Cela elimine les contraintes comptables qui existeraient si le processus enfant etait cree d'abord dans le meme cgroup que le parent puis deplace dans un cgroup cible. De plus, la creation d'un processus enfant directement dans un cgroup cible coute beaucoup moins cher que de deplacer le processus enfant dans le cgroup cible apres l'avoir cree. - L'attribut CLONE_INTO_CGROUP permet egalement la creation de processus enfants geles en les creant dans un cgroup gele (voir cgroups(7) pour une description des controleurs de gel). - Pour les applications threadees (voire meme les implementations de thread qui utilisent des cgroup pour limiter les threads individuels), il est possible d'etablir une couche de cgroup fixe avant de creer chaque thread directement dans son cgroup cible. CLONE_IO (depuis Linux 2.6.25) Si CLONE_IO est defini, alors le nouveau processus partage un contexte d'entrees-sorties avec le processus appelant. Si cet attribut n'est pas defini, alors (comme pour fork(2)) le nouveau processus a son propre contexte d'entrees-sorties. Le contexte d'entrees-sorties correspond a la visibilite que l'ordonnanceur de disques a des entrees-sorties (c'est-a-dire, ce que l'ordonnanceur d'entrees-sorties utilise pour modeliser l'ordonnancement des entrees-sorties d'un processus). Si des processus partagent le meme contexte d'entrees-sorties, ils sont traites comme un seul par l'ordonnanceur d'entrees-sorties. Par consequent, ils partagent le meme temps d'acces aux disques. Pour certains ordonnanceurs d'entrees-sorties, si deux processus partagent un contexte d'entrees-sorties, ils seront autorises a intercaler leurs acces disque. Si plusieurs threads utilisent des entrees-sorties pour le meme processus (aio_read(3), par exemple), ils devraient utiliser CLONE_IO pour obtenir de meilleures performances d'entrees-sorties. Si le noyau n'a pas ete configure avec l'option CONFIG_BLOCK, cet attribut n'a aucun effet. CLONE_NEWCGROUP (depuis Linux 4.6) Creer le processus dans un nouvel espace de noms cgroup. Si cet attribut n'est pas invoque, alors (comme pour fork(2)) le processus est cree dans le meme 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 privileges (CAP_SYS_ADMIN) peut utiliser CLONE_NEWCGROUP. CLONE_NEWIPC (depuis Linux 2.6.19) Si CLONE_NEWIPC est invoque, alors le processus est cree dans un nouvel espace de noms utilisateur IPC. Si cet attribut n'est pas invoque, alors (comme pour fork(2)) le processus est cree dans le meme espace de noms utilisateur IPC que le processus appelant. Pour plus d'informations sur les espaces de noms IPC, reportez vous a ipc_namespaces(7). Seul un processus disposant de privileges (CAP_SYS_ADMIN) peut utiliser CLONE_NEWIPC. Cet attribut ne peut pas etre employe en association avec CLONE_SYSVSEM. CLONE_NEWNET (depuis Linux 2.6.24) (L'implementation de cet attribut n'est complete que depuis Linux 2.6.29.) Si CLONE_NEWNET est invoque, alors le processus est cree dans un nouvel espace de noms reseau. Si cet attribut n'est pas invoque, alors (comme pour fork(2)) le processus est cree dans le meme espace de noms reseau que le processus appelant. Pour plus d'informations sur les espaces de noms reseau, reportez vous a network_namespaces(7). Seul un processus disposant de privileges (CAP_SYS_ADMIN) peut appeler CLONE_NEWNET. CLONE_NEWNS (depuis Linux 2.4.19) Si l'attribut CLONE_NEWNS est invoque, l'enfant clone demarre dans un nouvel espace de noms de montage, initialise avec une copie de l'espace de noms du parent. Si CLONE_NEWNS n'est pas invoque, alors l'enfant existe dans le meme espace de noms de montage que le parent. Pour plus d'informations sur les espaces de noms de montage, consultez namespaces(7) et mount_namespaces(7). Seul un processus disposant de privileges (CAP_SYS_ADMIN) peut utiliser l'attribut CLONE_NEWNS. Il n'est pas possible de specifier a la fois CLONE_NEWNS et CLONE_FS pour le meme appel clone. CLONE_NEWPID (depuis Linux 2.6.24) Si CLONE_NEWPID est invoque, alors le processus est cree dans un nouvel espace de noms PID. Si cet attribut n'est pas invoque, alors (comme pour fork(2)) le processus est cree dans le meme 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 privileges (CAP_SYS_ADMIN) peut utiliser CLONE_NEWPID. Cet attribut ne peut pas etre employe en association avec CLONE_THREAD. CLONE_NEWUSER (Cet attribut est apparu dans clone() pour la premiere fois dans Linux 2.6.23, les semantiques actuelles de clone() ont ete ajoutees dans Linux 3.5, et les derniers modules rendant les espaces de noms utilisateur completement operationnels sont apparus dans Linux 3.8.) Si CLONE_NEWUSER est invoque, alors le processus est cree dans un nouvel espace de noms utilisateur. Si cet attribut n'est pas invoque, alors (comme pour fork(2)) le processus est cree dans le meme 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 capacites pour utiliser CLONE_NEWUSER : CAP_SYS_ADMIN, CAP_SETUID et CAP_SETGID. A partir de Linux 3.8, il n'est plus necessaire de disposer de privileges pour creer des espaces de noms utilisateur. Cet attribut ne peut pas etre utilise en association avec CLONE_THREAD ou avec CLONE_PARENT. Pour des raisons de securite, CLONE_NEWUSER ne peut pas etre utilise en association avec CLONE_FS. CLONE_NEWUTS (depuis Linux 2.6.19) Si CLONE_NEWUTS est defini, creez le processus dans un nouvel espace de noms UTS, dont les identifiants sont initialises en dupliquant les identifiants de l'espace de noms UTS du processus appelant. Si cet attribut n'est pas defini, alors (comme pour fork(2)) le processus est cree dans le meme 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 privileges (CAP_SYS_ADMIN) peut utiliser CLONE_NEWUTS. CLONE_PARENT (depuis Linux 2.3.12) Si CLONE_PARENT est present, le parent du nouvel enfant (comme il est indique par getppid(2)) sera le meme 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'indique par getppid(2), qui est notifie lors de la fin de l'enfant. Ainsi, si CLONE_PARENT est present, alors c'est le parent du processus appelant, et non ce dernier, qui sera notifie. L'attribut CLONE_PARENT ne peut pas etre utilise 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 empeche la creation d'arbres de processus a plusieurs racines ou de zombies non recuperables dans l'espace de noms PID initial. CLONE_PARENT_SETTID (depuis Linux 2.5.49) Enregistrer l'ID du thread enfant a l'endroit vers lequel pointe parent_tid (clone()) ou cl_args.parent_tid (clone3()) dans la memoire du parent (dans Linux 2.5.32-2.5.48 il y a un attribut CLONE_SETTID qui fait cela). L'operation d'enregistrement s'acheve avant que l'operation clone ne donne le controle a l'espace utilisateur. CLONE_PID (de Linux 2.0 a Linux 2.5.15) Si l'attribut CLONE_PID est positionne, les processus appelant et enfant ont le meme numero de processus. C'est bien pour bidouiller le systeme, mais autrement il n'est plus utilise. Depuis Linux 2.3.21, cet attribut ne peut etre utilise que par le processus de demarrage du systeme (PID 0). Il a disparu dans Linux 2.5.16. Si bien que le noyau ignorait silencieusement le bit s'il etait indique dans le masque flags. Bien plus tard, le meme bit a ete recycle pour etre utilise comme attribut de CLONE_PIDFD. CLONE_PIDFD (depuis Linux 5.2) Si cet attribut est indique, un descripteur de fichier PID renvoyant au processus enfant est alloue et place a un endroit donne dans la memoire du parent. L'attribut close-on-exec est positionne sur ce nouveau descripteur de fichier. Les descripteurs de fichier PID peuvent etre utilises pour des objectifs decrits dans pidfd_open(2). - Quand on utilise clone3(), le descripteur de fichier PID est place a un endroit vers lequel pointe cl_args.pidfd. - Quand on utilise clone(), le descripteur de fichier PID est place a un endroit vers lequel pointe parent_tid. Comme le parametre parent_tid est utilise pour renvoyer le descripteur de fichier PID, CLONE_PIDFD ne peut pas etre utilise 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 identifie par le descripteur de fichier PID sera toujours un leader dans le groupe de threads. Si l'attribut obsolete CLONE_DETACHED est indique avec CLONE_PIDFD lors d'un appel a clone(), une erreur est renvoyee. Une erreur se produit aussi si CLONE_DETACHED est specifie lors d'un appel a clone3(). Ce comportement garantit que le bit qui correspond a CLONE_DETACHED pourra etre utilise a l'avenir pour des fonctionnalites supplementaires du descripteur de fichier PID. CLONE_PTRACE (depuis Linux 2.2) Si l'attribut CLONE_PTRACE est positionne et si l'appelant est suivi par un debogueur, alors l'enfant sera egalement suivi (consultez ptrace(2)). CLONE_SETTLS (depuis Linux 2.5.32) Le descripteur TLS (Thread Local Storage) est positionne sur tls. L'interpretation de tls et les effets qui en decoulent dependent de l'architecture. Sur x86, tls est interprete comme une struct user_desc * (voir set_thread_area(2)). Sur x86-64, il s'agit de la nouvelle valeur a positionner pour le registre de base %fs (voir le parametre ARCH_SET_FS de arch_prctl(2)). Sur les architectures ayant un registre TLS dedie, il s'agit de la nouvelle valeur de ce registre. L'utilisation de cet attribut exige une connaissance detaillee et n'est generalement pas souhaitable, sauf dans l'implementation de bibliotheques de gestion des threads. CLONE_SIGHAND (depuis Linux 2.0) Si l'attribut CLONE_SIGHAND est positionne, le processus appelant et le processus enfant partagent la meme table de gestionnaires de signaux. Si l'appelant, ou l'enfant, appelle sigaction(2) pour modifier le comportement associe a un signal, ce comportement est egalement change pour l'autre processus. Neanmoins, l'appelant et l'enfant ont toujours des masques de signaux distincts, et leurs ensembles de signaux bloques sont independants. L'un des processus peut donc bloquer ou debloquer un signal en utilisant sigprocmask(2) sans affecter l'autre processus. Si CLONE_SIGHAND n'est pas utilise, le processus enfant herite d'une copie des gestionnaires de signaux de l'appelant lors de l'invocation de clone(). Les appels a sigaction(2) effectues ensuite depuis l'un des 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 specifie CLONE_STOPPED (depuis Linux 2.6.0) Si l'attribut CLONE_STOPPED est positionne, l'enfant est initialement stoppe (comme s'il avait recu le signal SIGSTOP), et doit etre relance en lui envoyant le signal SIGCONT. Cet attribut a ete rendu obsolete par Linux 2.6.25, puis il a ete supprime dans Linux 2.6.38. Depuis lors, le noyau l'ignore silencieusement sans erreur. A partir de Linux 4.6, le meme bit a ete reutilise comme attribut de CLONE_NEWCGROUP. CLONE_SYSVSEM (depuis Linux 2.5.10) Si CLONE_SYSVSEM est positionne, l'enfant et le processus appelant partagent une meme liste de valeurs d'ajustement de semaphores System V (consultez semop(2)). Dans ce cas, cette liste regroupe toutes les valeurs semadj des processus partageant cette liste, et les modifications des semaphores sont effectuees 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 utilise, l'enfant a une liste semadj separee, initialement vide. CLONE_THREAD (depuis Linux 2.4.0) Si CLONE_THREAD est present, l'enfant est place dans le meme groupe de threads que le processus appelant. Afin de rendre l'explication de CLONE_THREAD plus lisible, le terme << thread >> est utilise pour parler des processus dans un meme groupe de threads. Les groupes de threads sont une fonctionnalite ajoutee dans Linux 2.4 pour gerer la notion POSIX d'ensemble de threads partageant un meme PID. En interne, ce PID partage est appele identifiant de groupe de threads (TGID). Depuis Linux 2.4, l'appel getpid(2) renvoie l'identifiant du groupe de threads de l'appelant. Les threads dans un groupe peuvent etre distingues par leur identifiant de thread (TID, unique sur le systeme). Le TID d'un nouveau thread est disponible sous la forme du resultat d'une fonction renvoye a l'appelant et un thread peut obtenir son propre TID en utilisant gettid(2). Quand clone est appele sans positionner CLONE_THREAD, le nouveau thread est place dans un nouveau groupe de threads dont le TGID est identique au TID du nouveau thread. Ce thread est le leader du nouveau groupe. Un nouveau thread cree en utilisant CLONE_THREAD a le meme processus parent que le processus realisant l'appel clone (de meme qu'avec CLONE_PARENT), ainsi les appels a getppid(2) renvoient la meme valeur a tous les threads dans un meme groupe. Lorsqu'un thread cree avec CLONE_THREAD termine, le thread qui l'a cree ne recoit pas le signal SIGCHLD (ou autre notification de terminaison) ; de meme, l'etat d'un tel thread ne peut pas etre obtenu par wait(2). Le thread est dit detache. Lorsque tous les threads d'un groupe de threads terminent, le processus parent du groupe recoit un signal SIGCHLD (ou un autre indicateur de terminaison). Si l'un des threads dans un groupe de threads appelle execve(2), tous les threads sauf le leader sont tues, et le nouveau programme est execute dans le leader du groupe de threads. Si l'un des threads dans un groupe cree 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 specifie (et remarquez que depuis Linux 2.6.0, CLONE_SIGHAND a egalement besoin de CLONE_VM). Les gestions de signaux sont definies au niveau des processus : si un signal sans gestionnaire est recu par un thread, il affectera (tuera, stoppera, relancera, ou sera ignore par) tous les membres du groupe de threads. Chaque thread a son propre masque de signal, tel que defini par sigprocmask(2). Un signal peut etre adresse a un processus ou a un thread. S'il s'adresse a un processus, il cible un groupe de threads (c'est-a-dire un TGID), et il est envoye a un thread choisi arbitrairement parmi ceux ne bloquant pas les signaux. Un signal peut s'adresser a un processus car il est genere par le noyau pour d'autres raisons qu'une exception materielle, ou parce qu'il a ete envoye en utilisant kill(2) ou sigqueue(3). Si un signal s'adresse a un thread, il cible (donc est envoye) a un thread specifique. Un signal peut s'adresser a un thread du fait d'un envoi par tgkill(2) ou pthread_sigqueue(3), ou parce que le thread a execute une instruction en langage machine qui a provoque une exception materielle (comme un acces non valable en memoire, provoquant SIGSEGV, ou une exception de virgule flottante provoquant un SIGFPE). Un appel a sigpending(2) renvoie un jeu de signaux qui reunit les signaux en attente adresses au processus et ceux en attente pour le thread appelant. Si un signal adresse a un processus est envoye a un groupe de threads, et si le groupe a installe un gestionnaire pour ce signal, alors le gestionnaire sera execute exactement dans un des membres du groupe de threads, choisi de facon arbitraire parmi ceux qui n'ont pas bloque ce signal. Si plusieurs threads dans un groupe attendent le meme 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 positionne, alors un processus tracant 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'execution du processus appelant est suspendue jusqu'a ce que l'enfant libere ses ressources de memoire virtuelle par un appel execve(2) ou _exit(2) (comme avec vfork(2)). Si CLONE_VFORK n'est pas indique, alors les deux processus sont ordonnances a partir de la fin de l'appel, et l'application ne devrait pas considerer que l'ordre d'execution est determine 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'executent dans le meme espace memoire. En particulier, les ecritures en memoire effectuees par l'un des processus sont visibles par l'autre. De meme toute projection en memoire, ou toute suppression de projection, effectuee avec mmap(2) ou munmap(2) par l'un des processus affectera egalement l'autre processus. Si CLONE_VM n'est pas actif, le processus enfant utilisera une copie distincte de l'espace memoire de l'appelant au moment de l'appel clone. Les ecritures ou les associations/desassociations de fichiers en memoire effectuees par un processus n'affectent pas l'autre processus, comme cela se passe avec fork(2). Si l'attribut CLONE_VM est indique et si l'attribut CLONE_VFORK ne l'est pas, toute autre pile de signal mise en place par sigaltstack(2) sera videe dans le processus enfant. VALEUR RENVOYEE En cas de reussite, le TID du processus enfant est renvoye dans le thread d'execution de l'appelant. En cas d'echec, -1 est renvoye dans le contexte de l'appelant, aucun enfant n'est cree, et errno sera positionne pour indiquer l'erreur. ERREURS EACCES (clone3() seulement) CLONE_INTO_CGROUP etait indique dans cl_args.flags, mais les restrictions a la mise en place d'un processus enfant dans un cgroup version 2 auquel se rapporte cl_args.cgroup (decrites dans cgroups(7)) ne sont pas respectees. EAGAIN Trop de processus en cours d'execution. Consultez fork(2). EBUSY (clone3() seulement) CLONE_INTO_CGROUP etait indique dans cl_args.flags, mais le descripteur de fichier indique dans cl_args.cgroup se rapporte a un cgroup version 2 ou un controleur de domaine est active. EEXIST (clone3() seulement) Un (ou plusieurs) PID indique dans le set_tid existe deja dans l'espace de noms PID correspondant. EINVAL Tant CLONE_SIGHAND que CLONE_CLEAR_SIGHAND ont ete indiques dans le masque flags. EINVAL CLONE_SIGHAND a ete specifie dans le masque flags, mais pas CLONE_VM (depuis Linux 2.6.0). EINVAL CLONE_THREAD a ete specifie dans le masque flags, mais pas CLONE_SIGHAND (depuis Linux 2.5.35). EINVAL CLONE_THREAD a ete indique dans le masque flags mais le processus actuel avait appele unshare(2) avec l'attribut CLONE_NEWPID ou il utilisait setns(2) pour se reassocier a l'espace de noms PID. EINVAL Tant CLONE_FS que CLONE_NEWNS ont ete indiques dans le masque flags. EINVAL (depuis Linux 3.9) Tant CLONE_NEWUSER que CLONE_FS ont ete indiques dans le masque flags. EINVAL Tant CLONE_NEWIPC que CLONE_SYSVSEM ont ete indiques dans le masque flags. EINVAL CLONE_NEWPID et CLONE_THREAD ou CLONE_PARENT, seuls ou ensemble,ont ete indiques dans le masque flags. EINVAL CLONE_NEWUSER et CLONE_THREAD ont ete indiques dans le masque flags. EINVAL (depuis Linux 2.6.32) CLONE_PARENT a ete specifie et l'appelant est un processus d'initialisation. EINVAL Renvoyee par l'enveloppe glibc de clone() quand fn ou stack valent NULL. EINVAL CLONE_NEWIPC a ete specifie dans le masque flags, mais le noyau n'a pas ete configure avec les options CONFIG_SYSVIPC et CONFIG_IPC_NS. EINVAL CLONE_NEWNET a ete specifie dans le masque flags, mais le noyau n'a pas ete configure avec l'option CONFIG_NET_NS. EINVAL CLONE_NEWPID a ete specifie dans le masque flags, mais le noyau n'a pas ete configure avec l'option CONFIG_PID_NS. EINVAL CLONE_NEWUSER a ete specifie dans le masque flags, mais le noyau n'a pas ete configure avec l'option CONFIG_USER_NS. EINVAL CLONE_NEWUTS a ete specifie dans le masque flags, mais le noyau n'a pas ete configure avec l'option CONFIG_UTS_NS. EINVAL stack n'est pas alignee sur une limite adaptee a cette architecture. Par exemple, sur aarch64, stack doit etre un multiple de 16. EINVAL (clone3() seulement) CLONE_DETACHED a ete specifie dans le masque flags. EINVAL (clone() seulement) CLONE_PIDFD a ete indique avec CLONE_DETACHED dans le masque flags. EINVAL CLONE_PIDFD a ete indique avec CLONE_THREAD dans le masque flags. EINVAL (clone() seulement) CLONE_PIDFD a ete indique avec CLONE_PARENT_SETTID dans le masque flags. EINVAL (clone3() seulement) set_tid_size est superieur au nombre de niveaux dans l'espace de noms PID. EINVAL (clone3() seulement) Un des PID indique dans set_tid n'etait pas valable. EINVAL (clone3() seulement) CLONE_THREAD ou CLONE_PARENT ont ete specifies dans le masque flags, mais un signal a ete specifie dans exit_signal. EINVAL (AArch64 seulement, Linux 4.6 et anterieur) stack n'etait pas aligne sur une limite de 128 bits. ENOMEM Pas assez de memoire pour copier les parties du contexte du processus appelant qui doivent etre dupliquees, ou pour allouer une structure de tache pour le processus enfant. ENOSPC (depuis Linux 3.7) CLONE_NEWPID a ete specifie dans le masque flags, et l'appel provoquerait un depassement de la limite du nombre maximal d'espaces de noms utilisateur imbriques. Consultez pid_namespaces(7). ENOSPC (depuis Linux 4.9 ; auparavant EUSERS) CLONE_NEWUSER a ete specifie dans le masque flags, et l'appel provoquerait un depassement de la limite du nombre maximal d'espaces de noms utilisateur imbriques. Consultez user_namespaces(7). De Linux 3.11 a Linux 4.8, l'erreur indiquee dans ce cas etait EUSERS. ENOSPC (depuis Linux 4.9) Une des valeurs dans le masque flags indiquait de creer un nouvel espace de noms utilisateur, mais cela aurait provoque un depassement de la limite definie par le fichier correspondant dans /proc/sys/user. Pour plus de details, voir namespaces(7). EOPNOTSUPP (clone3() seulement) CLONE_INTO_CGROUP etait indique dans cl_args.flags, mais le descripteur de fichier indique dans cl_args.cgroup se rapporte a un cgroup version 2 dont l'etat est domain invalid. EPERM CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID ou CLONE_NEWUTS a ete specifie par un processus non privilegie (processus sans CAP_SYS_ADMIN). EPERM CLONE_PID a ete specifie par un processus autre que le processus 0 (cette erreur n'arrive que sur Linux 2.5.15 et anterieurs). EPERM CLONE_NEWUSER a ete specifie 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 ete specifie dans le masque flags et l'appelant se trouve dans un environnement chroot (c'est-a-dire que le repertoire racine de l'appelant ne correspond pas au repertoire racine de l'espace de noms de montage dans lequel il se trouve). EPERM (clone3() seulement) set_tid_size etait superieur a zero et l'appelant n'a pas la capacite CAP_SYS_ADMIN dans un ou plusieurs des espaces de noms utilisateur qui possedent les espaces de noms PID correspondants. ERESTARTNOINTR (depuis Linux 2.6.17) L'appel systeme a ete interrompu par un signal et va etre redemarre (cela n'est visible qu'a l'occasion d'un trace()). EUSERS (Linux 3.11 a Linux 4.8) CLONE_NEWUSER a ete specifie dans le masque flags, et l'appel provoquerait un depassement de la limite du nombre maximal d'espaces de noms utilisateur imbriques. Voir le point sur l'erreur ENOSPC ci-dessus. VERSIONS La fonction enveloppe clone() de la glibc effectue des changements dans la memoire vers laquelle pointe stack (ce sont des changements necessaires pour positionner correctement la pile pour l'enfant) avant de recourir a l'appel systeme clone(). Des lors, lorsque clone() est utilise pour creer des enfants de maniere recursive, n'utilisez pas le tampon servant a la pile du parent en tant que pile de l'enfant. Sur i386, clone() ne devrait pas etre appele a l'aide de vsyscall, mais directement en utilisant int $0x80. Differences entre bibliotheque C et noyau L'appel systeme clone brut ressemble plus a fork(2), en ceci que l'execution dans le processus enfant continue a partir du point d'appel. A ce titre, les arguments fn et arg de la fonction enveloppe de clone() sont omis. Contrairement a l'enveloppe de la glibc, l'appel systeme brut clone() accepte NULL en parametre de stack (et de meme, clone3() permet a cl_args.stack d'etre NULL). Dans ce cas l'enfant utilise une copie de la pile du parent (la semantique de copie-en-ecriture assure que l'enfant recevra une copie independante des pages de la pile des qu'un des deux processus la modifiera). Pour que cela fonctionne, il faut naturellement que CLONE_VM ne soit pas present (si l'enfant partage la memoire du parent du fait d'une utilisation de CLONE_VM, aucune duplication a l'aide de la copie-en-ecriture ne se produit et il peut s'ensuivre probablement un grand chaos). L'ordre des parametres change aussi dans l'appel systeme brut et des variations existent dans les parametres en fonction des architectures, comme indique dans les paragraphes suivants. L'interface de l'appel systeme 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 parametres est inverse : 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 parametres est inverse : long clone(void *stack, unsigned long flags, int *parent_tid, int *child_tid, unsigned long tls); Sur l'architecture microblaze, il existe un parametre supplementaire : 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 differentes de celles decrites precedemment. Pour plus de details, se referer aux sources du noyau (et de la glibc). ia64 Sur ia64, une interface differente est utilisee : 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 presente ci-dessus vaut pour la fonction enveloppe de la glibc ; pour l'appel systeme lui-meme, il peut etre decrit 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. STANDARDS Linux. HISTORIQUE clone3() Linux 5.3. Linux 2.4 et anterieurs Dans les series 2.4.x de Linux, CLONE_THREAD ne fait en general pas du processus parent du nouveau thread un processus identique au parent du processus appelant. Cependant, de Linux 2.4.7 a Linux 2.4.18, l'attribut CLONE_THREAD impliquait CLONE_PARENT (de meme que dans Linux 2.6.0 et superieurs). Sous Linux 2.4 et plus anciens, clone() ne prend pas les parametres parent_tid, tls, et child_tid. NOTES Une utilisation de ces appels systeme consiste a implementer des threads : un programme est scinde en plusieurs lignes de controle, s'executant simultanement dans un espace memoire partagee. L'appel systeme kcmp(2) peut etre utilise pour verifier si deux processus partagent des ressources, telles qu'une table de descripteurs de fichier, des operations Annuler le semaphore sur System V, ou un espace d'adressage virtuel. Les gestionnaires enregistres en utilisant pthread_atfork(3) ne sont pas executes pendant un appel clone. BOGUES Les versions de la bibliotheque C GNU jusqu'a la 2.24 comprise contenaient une fonction enveloppe pour getpid(2) qui effectuait un cache des PID. Ce cache necessitait une prise en charge par l'enveloppe de clone() de la glibc, mais des limites dans l'implementation faisaient que le cache pouvait ne pas etre a jour sous certaines circonstances. En particulier, si un signal etait distribue a un enfant juste apres l'appel a clone(), alors un appel a 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 a jour pour l'enfant. (Ce point ignore le cas ou l'enfant a ete cree en utilisant CLONE_THREAD, quand getpid(2) doit renvoyer la meme valeur pour l'enfant et pour le processus qui a appele clone(), puisque l'appelant et l'enfant se trouvent dans le meme groupe de threads. Ce probleme de cache n'apparait pas non plus si le parametre flags contient CLONE_VM.) Pour obtenir la veritable valeur, il peut etre necessaire d'utiliser quelque chose comme ceci : #include pid_t mypid; mypid = syscall(SYS_getpid); Suite a un probleme de cache ancien, ainsi qu'a d'autres problemes traites dans getpid(2), la fonctionnalite de mise en cache du PID a ete supprimee de la glibc 2.25. EXEMPLES Le programme suivant decrit l'usage de clone() dans le but de creer un processus enfant qui s'execute dans un espace de noms UTS distinct. Le processus enfant change le nom d'hote (hostname) dans son propre espace UTS. Les processus parent et enfant affichent chacun le nom d'hote qui leur correspond, permettant ainsi de constater la difference des noms d'hotes 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 memoire qui doit etre utilisee 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 memoire commencant a la limite d'une page et qui est un multiple de la taille de la page. Cela est utile si on veut etablir une page de protection (avec PROT_NONE) a la fin de la pile en utilisant mprotect(2). - On peut indiquer l'attribut MAP_STACK pour demander une association adaptee a une pile. Pour le moment, cet attribut n'est pas operationnel sur Linux, mais il existe et a des effets sur d'autres systemes, donc on doit l'inclure pour la portabilite. Source du programme #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include static int /* Commencer la fonction pour l'enfant clone */ childFunc(void *arg) { struct utsname uts; /* Modifier le nom d'hote dans l'espace de noms UTS de l'enfant. */ if (sethostname(arg, strlen(arg)) == -1) err(EXIT_FAILURE, "sethostname"); /* Recuperer et afficher le nom d'hote. */ if (uname(&uts) == -1) err(EXIT_FAILURE, "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 realiser quelques experimentations -- par exemple, un autre processus pourrait rejoindre l'espace de noms. */ sleep(200); return 0; /* Le processus enfant se termine a ce moment */ } #define STACK_SIZE (1024 * 1024) /* Taille de la pile pour l'enfant clone */ int main(int argc, char *argv[]) { char *stack; /* Debut 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 \n", argv[0]); exit(EXIT_SUCCESS); } /* Allouer la memoire a 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) err(EXIT_FAILURE, "mmap"); stackTop = stack + STACK_SIZE; /* On suppose que la pile grandit vers le bas */ /* Creer un processus enfant disposant de son propre espace de noms UTS ; le processus enfant debute son execution dans childFunc(). */ pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]); if (pid == -1) err(EXIT_FAILURE, "clone"); printf("clone() a renvoye %jd\n", (intmax_t) pid); /* Le parent se retrouve ici */ sleep(1); /* Laisser le temps au processus enfant de changer son nom d'hote */ /* Afficher le nom d'hote pour l'espace de noms UTS du processus parent. Celui-ci sera different du nom d'hote pour l'espace de noms UTS du processus enfant. */ if (uname(&uts) == -1) err(EXIT_FAILURE, "uname"); printf("uts.nodename dans le parent : %s\n", uts.nodename); if (waitpid(pid, NULL, 0) == -1) /* Attendre le processus enfant */ err(EXIT_FAILURE, "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) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Cedric Boutillier , Frederic Hantrais et Jean-Philippe MENGUAL Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 1 novembre 2023 clone(2)