Provided by: manpages-fr-dev_4.23.1-1_all bug

NOM

       vfork - Créer un processus enfant et bloquer le parent

BIBLIOTHÈQUE

       Bibliothèque C standard (libc, -lc)

SYNOPSIS

       #include <unistd.h>

       pid_t vfork(void);

   Exigences    de    macros    de   test   de   fonctionnalités   pour   la   glibc   (consulter
   feature_test_macros(7)) :

       vfork() :
           Depuis la glibc 2.12 :
               (_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)
                   || /* Depuis la glibc 2.19 : */ _DEFAULT_SOURCE
                   || /* glibc <= 2.19 : */ _BSD_SOURCE
           Avant la glibc 2.12 :
               _BSD_SOURCE || _XOPEN_SOURCE >= 500

DESCRIPTION

   Description des normes
       (D'après POSIX.1).  La  routine  vfork()  a  le  même  effet  que  fork(2),  sauf  que  le
       comportement  est  indéfini  si  le  processus créé par vfork() effectue l'une des actions
       suivantes avant d'appeler avec succès _exit(2) ou une  routine  de  la  famille  exec(3) :
       modification  d'une  donnée  autre  que  la  variable  de type pid_t stockant le retour de
       vfork(), revenir de la fonction dans laquelle vfork() a été  invoqué,  appel  d'une  autre
       fonction.

   Description de l'implémentation Linux
       vfork(), tout comme fork(2), crée un processus enfant à partir du processus appelant. Pour
       plus de détails sur les valeurs renvoyées et les erreurs possibles, consultez fork(2).

       vfork() est conçu comme un cas particulier  de  clone(2).  Il  sert  à  créer  un  nouveau
       processus  sans effectuer de copie de la table des pages mémoire du processus parent. Cela
       peut être utile dans des applications nécessitant  une  grande  rapidité  d'exécution,  si
       l'enfant doit invoquer immédiatement un appel execve(2).

       vfork()  diffère  de  fork(2)  en  ce que le thread appelant reste suspendu jusqu'à ce que
       l'enfant se termine (soit normalement, en appelant _exit(2), soit de façon anormale  après
       l'envoi  d'un signal fatal) ou qu'il appelle execve(2). Jusqu'à ce point, l'enfant partage
       toute la mémoire avec son parent, y compris la pile.  Le  processus  enfant  ne  doit  pas
       revenir  de  la  fonction en cours, ni appeler exit(3) (ce qui aurait pour effet d'appeler
       les gestionnaires de sortie établis par le  processus  parent  et  de  vider  les  tampons
       stdio(3) du parent), mais appeler à _exit(2).

       Comme  avec  fork(2),  le processus enfant créé par vfork() hérite des copies de plusieurs
       attributs  du  processus  appelant  (par  exemple  les  descripteurs  de   fichiers,   les
       dispositions  des  signaux  et  le répertoire de travail actuel) ; l'appel vfork() diffère
       seulement par le traitement de l'espace d'adressage virtuel, comme décrit ci-dessus.

       Les signaux pour le processus parent sont délivrés après que l'enfant libère la mémoire du
       parent (c'est-à-dire après que l'enfant se termine ou qu'il appelle execve(2)).

   Description historique
       Sous  Linux,  fork(2) est implémenté en utilisant un mécanisme de copie en écriture, ainsi
       ses seuls coûts sont le temps et la mémoire nécessaire pour dupliquer la table  des  pages
       mémoire  du  processus  parent,  et  créer  une  seulestructure  de  tâche  pour l'enfant.
       Toutefois, jadis fork(2) nécessitait malheureusement une copie  complète  de  l'espace  de
       données  du  parent,  souvent  inutilement,  car  un  appel  exec(3)  est  souvent réalisé
       immédiatement par l'enfant. Pour améliorer les performances,  BSD  a  introduit  un  appel
       système  vfork()  qui ne copie pas l'espace d'adressage du parent, mais emprunte au parent
       son espace d'adressage et son fil de contrôle jusqu'à  un  appel  à  execve(2)  ou  qu'une
       sortie  survienne.  Le  processus  parent  était  suspendu tant que l'enfant utilisait les
       ressources. L'utilisation de vfork()  était  loin  d'être  facile,  car,  pour  éviter  de
       modifier  les  données  du processus parent, il fallait être capable de déterminer quelles
       variables se trouvaient dans des registres du processeur.

VERSIONS

       Les exigences que les normes apportent sur vfork() sont  plus  relâchées  que  celles  sur
       fork(2), ainsi il est possible d'avoir une implémentation conforme où les deux appels sont
       synonymes. En particulier, un programmeur ne doit pas s'appuyer sur le fait que le  parent
       reste  bloqué  jusqu'à  ce  que  l'enfant  se  termine  ou  appelle  execve(2),  ni sur le
       comportement par rapport à la mémoire partagée.

       Certaines personnes considèrent la sémantique de vfork() comme une verrue  architecturale,
       et  la  page  de  manuel de 4.2BSD indique que « cet appel système sera supprimé quand des
       mécanismes de partage appropriés seront implémentés. Il  ne  faut  pas  essayer  de  tirer
       profit  du  partage  mémoire induit par vfork, car dans ce cas il serait rendu synonyme de
       fork(2) ». Cependant, même si  le  matériel  de  gestion  mémoire  moderne  a  diminué  la
       différence  de  performances  entre  fork(2)  et  vfork(), il existe diverses raisons pour
       lesquelles Linux et d'autres systèmes ont conservé vfork() :

       -  Certaines applications de haute performance  ont  besoin  du  petit  gain  apporté  par
          vfork().

       -  vfork()  peut être implémenté sur des systèmes sans unité de gestion mémoire (MMU, pour
          « memory-management unit »), mais fork(2) ne peut  pas  être  implémenté  sur  de  tels
          systèmes  (POSIX.1-2008  a  supprimé vfork() de la norme ; la raison invoquée par POSIX
          pour la fonction posix_spawn(3) note que cette fonction, qui fournit une fonctionnalité
          équivalente  à  fork(2)+  exec(3),  est conçue pour être implémentable sur des systèmes
          sans MMU).

       -  Sur les systèmes où la mémoire est restreinte, vfork évite le besoin  d'allouer  de  la
          mémoire  temporairement  (voir  la  description  de /proc/sys/vm/overcommit_memory dans
          proc(5))  afin  d'exécuter  un  nouveau  programme.  Cela  peut  être  particulièrement
          bénéfique  lorsqu'un  grand  processus  parent  souhaite  exécuter  un  petit programme
          d'assistance dans un processus enfant. Par contraste, l'utilisation de fork(2) dans  ce
          scénario  nécessite  soit  l'allocation  d'une quantité de mémoire égale à la taille du
          processus parent  (si  la  gestion  stricte  du  dépassement  est  en  cours)  soit  un
          dépassement  de  mémoire avec le risque qu'un processus soit terminé par la mise à mort
          sur mémoire saturée (OOM killer).

   Notes pour Linux
       Les gestionnaires  enregistrés  avec  pthread_atfork(3)  ne  sont  pas  appelés  lorsqu'un
       programme  multithreadé  utilisant  la  bibliothèque  de  threads NPTL appelle vfork(). En
       revanche  ces  gestionnaires  sont  appelés  si  le  programme  utilise  la   bibliothèque
       LinuxThreads.  (Consultez  pthreads(7)  pour  une description des bibliothèques de threads
       pour Linux.)

       Un appel à vfork() est équivalent à appeler clone(2) avec flags valant :

            CLONE_VM | CLONE_VFORK | SIGCHLD

STANDARDS

       Aucun.

HISTORIQUE

       4.3BSD, POSIX.1-2001 (mais la déclare obsolète). POSIX.1-2008 supprime la spécification de
       vfork().

       L'appel  système  vfork()  est  apparu dans 3.0BSD. Dans 4.4BSD, il est devenu synonyme de
       fork(2),  mais  NetBSD  l'a  réintroduit  à  nouveau   (consultez   ⟨http://www.netbsd.org
       /Documentation/kernel/vfork.html⟩  ). Sous Linux, il a été l'équivalent de fork(2) jusqu'à
       Linux 2.2.0-pre-6. Depuis Linux 2.2.0-pre-9 (sur i386,  un  peu  plus  tard  sur  d'autres
       architectures),  il  s'agit  d'un  appel  système  indépendant.  La  prise en charge a été
       introduite dans la glibc 2.0.112.

AVERTISSEMENTS

       Le processus enfant devrait veiller à ne pas modifier la mémoire d'une manière inattendue,
       dans  la  mesure  où  les  modifications  seront vues par le processus parent une fois que
       l'enfant s'est achevé ou exécute un autre programme. À cet  égard,  les  gestionnaires  de
       signaux  peuvent  être  particulièrement problématiques : si un gestionnaire de signal qui
       est invoqué dans l'enfant d'un vfork()  modifie  la  mémoire,  ces  modifications  peuvent
       aboutir  à  une  inconsistance  de l'état du processus du point de vue du processus parent
       (par exemple, les modifications de la mémoire pourraient être  visibles  dans  le  parent,
       mais pas les modifications de l'état des descripteurs de fichiers ouverts).

       Lorsque  vfork()  est  appelé  dans un processus multithreadé, seul le thread appelant est
       suspendu jusqu'à ce que l'enfant s'achève ou exécute un nouveau programme.  Cela  signifie
       que  l'enfant  partage  un espace d'adresses avec un autre code en cours d'exécution. Cela
       peut être dangereux si un autre thread dans le processus parent  modifie  son  identifiant
       (avec  setuid(2)  ou  une  autre  commande similaire), dans la mesure où il y a alors deux
       processus avec différents niveaux de privilèges exécutés dans le même  espace  d'adresses.
       Comme  exemple  de  risque,  imaginez  qu'un  programme  multithreadé  exécuté en tant que
       superutilisateur crée un enfant  avec  vfork().  Après  le  vfork(),  un  thread  dans  le
       processus parent transfère le processus à un utilisateur non privilégié afin d'exécuter du
       code non sûr (par exemple, peut-être au moyen d'un greffon ouvert avec dlopen(3)). Dans ce
       cas,  des  attaques sont possibles où le processus parent utilise mmap(2) pour projeter en
       mémoire du code qui sera exécuté par le processus enfant privilégié.

BOGUES

       Les détails de la gestion des signaux sont compliqués et varient suivant les systèmes.  La
       page  de  manuel  BSD  indique :  « Pour éviter une possible situation d'interblocage, les
       processus qui sont des enfants au milieu  d'un  vfork()  ne  reçoivent  jamais  le  signal
       SIGTTOU  ou  SIGTTIN ;  des  sorties  et  des ioctl sont autorisés, mais des tentatives de
       lecture donneront une indication de fin de fichier. »

VOIR AUSSI

       clone(2), execve(2), _exit(2), fork(2), unshare(2), wait(2)

TRADUCTION

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

       Cette traduction est une documentation libre ; veuillez vous reporter  à  la  GNU  General
       Public   License   version 3  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩  concernant  les
       conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

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