Provided by: manpages-fr-dev_4.21.0-2_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.

STANDARDS

       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'à  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.

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