NOM
vfork - Créer un processus fils et bloquer le père
SYNOPSIS
#include
<sys/types.h>
#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)
|| /* Since glibc 2.19: */ _DEFAULT_SOURCE
|| /* Glibc versions <= 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 fils à 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 père. Ceci peut être utile dans des applications nécessitant une grande rapidité d’exécution, si le fils doit invoquer immédiatement un appel execve(2).
vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child must not return from the current function or call exit(3) (which would have the effect of calling exit handlers established by the parent process and flushing the parent’s stdio(3) buffers), but may call _exit(2).
Comme avec fork(2), le processus fils 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 père sont délivrés après que le fils libère la mémoire du père (c’est-à-dire après que le fils 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 père, et
créer une structure de tâche pour le fils.
Toutefois, jadis fork(2) nécessitait
malheureusement une copie complète de l’espace
d’adresse du père, souvent inutile car un appel
exec(3) est souvent réalisé
immédiatement par le fils. Pour améliorer les
performances, BSD a introduit un appel système
vfork() qui ne copie pas l’espace
d’adressage du père, mais emprunte au parent
son espace d’adressage et son fil de contrôle
jusqu’à un appel à execve(2) ou
exit. Le processus père était suspendu tant
que le fils utilisait les ressources. L’utilisation de
vfork() était loin d’être facile,
car pour éviter de modifier les données du
processus père, il fallait être capable de
déterminer quelles variables se trouvaient dans des
registres du processeur.
CONFORMITÉ
BSD 4.3, POSIX.1-2001 (mais la déclare obsolète). POSIX.1-2008 supprime la spécification de vfork().
Les exigences que les standards 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 père reste bloqué jusqu’à ce que le fils 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 BSD 4.2 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 sera rendu synonyme de fork(2) ». Cependant, même si le matériel de gestion mémoire matériel 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). | ||
* |
On systems where memory is constrained, vfork() avoids the need to temporarily commit memory (see the description of /proc/sys/vm/overcommit_memory in proc(5)) in order to execute a new program. (This can be especially beneficial where a large parent process wishes to execute a small helper program in a child process.) By contrast, using fork(2) in this scenario requires either committing an amount of memory equal to the size of the parent process (if strict overcommitting is in force) or overcommitting memory with the risk that a process is terminated by the out-of-memory (OOM) killer. |
Mises en
garde
The child process should take care not to modify the memory
in unintended ways, since such changes will be seen by the
parent process once the child terminates or executes another
program. In this regard, signal handlers can be especially
problematic: if a signal handler that is invoked in the
child of vfork() changes memory, those changes may
result in an inconsistent process state from the perspective
of the parent process (e.g., memory changes would be visible
in the parent, but changes to the state of open file
descriptors would not be visible).
When vfork() is called in a multithreaded process, only the calling thread is suspended until the child terminates or executes a new program. This means that the child is sharing an address space with other running code. This can be dangerous if another thread in the parent process changes credentials (using setuid(2) or similar), since there are now two processes with different privilege levels running in the same address space. As an example of the dangers, suppose that a multithreaded program running as root creates a child using vfork(). After the vfork(), a thread in the parent process drops the process to an unprivileged user in order to run some untrusted code (e.g., perhaps via plug-in opened with dlopen(3)). In this case, attacks are possible where the parent process uses mmap(2) to map in code that will be executed by the privileged child process.
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
The vfork() system call appeared in 3.0BSD. In 4.4BSD
it was made synonymous to fork(2) but NetBSD
introduced it again; see
http://www.netbsd.org/Documentation/kernel/vfork.html">http://www.netbsd.org/Documentation/kernel/vfork.html.
In Linux, it has been equivalent to fork(2) until
2.2.0-pre6 or so. Since 2.2.0-pre9 (on i386, somewhat later
on other architectures) it is an independent system call.
Support was added in 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 fils 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.07 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 [AT] laposte.net>, Thierry Vignaud <tvignaud [AT] mandriva.com>, François Micaux, Alain Portal <aportal [AT] univ-montp2.fr>, Jean-Philippe Guérard <fevrier [AT] tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon [AT] wanadoo.fr>, Julien Cristau <jcristau [AT] debian.org>, Thomas Huriaux <thomas.huriaux [AT] gmail.com>, Nicolas François <nicolas.francois [AT] centraliens.net>, Florentin Duneau <fduneau [AT] gmail.com>, Simon Paillard <simon.paillard [AT] resel.fr>, Denis Barbier <barbier [AT] debian.org> et David Prévot <david [AT] tilapin.org>
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 [AT] lists.org>.