Provided by: manpages-fr-dev_4.15.0-9_all bug

NOM

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

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.

CONFORMITÉ

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

       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.

NOTES

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

   Mises en garde
       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é.

   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

   Historique
       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'au
       noyau 2.2.0-pre-6. Depuis le noyau 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 dans la
       bibliothèque a été introduite dans la glibc 2.0.112.

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)

COLOPHON

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

TRADUCTION

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