Provided by: manpages-fr-dev_4.27.0-1_all 

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 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.
Pages du manuel de Linux 6.9.1 2 mai 2024 vfork(2)