Linux |
CentOS 4.8 |
|
vfork(2) |
vfork − Créer un processus fils et bloquer le père. |
#include <sys/types.h> pid_t vfork(void); |
(D’après XPG4 / SUSv2 / draft POSIX). La routine vfork(), à le même effet que fork(), sauf que le comportement est indéfini si le processus créé par fork() effectue l’une des actions suivantes avant d’appeler avec succès _exit() ou une routine de la famille exec() : 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. |
ENOMEM |
Pas assez de mémoire |
|||
EAGAIN |
Trop de processus en cours. Réessayer. |
vfork(), tout comme fork(), crée un processus fils à partir du processus appelant. Pour plus de détails sur les valeurs renvoyées et les erreurs possibles, voir 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(). vfork() diffère aussi de fork() car le processus père reste suspendu jusqu’à ce que le fils invoque execve(), ou _exit(). Le fils partage toute la mémoire avec son père, y compris la pile. Le processus fils ne doit donc pas revenir de la fonction en cours, ni invoquer une nouvelle routine. Il ne doit pas appeler exit(), mais à la place _exit(). Les gestionnaires de signaux sont hérités mais pas partagés. Les signaux pour le processus père sont délivrés après que le fils se soit terminé. |
Sous Linux, fork() 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() nécessitait malheureusement une copie complète de l’espace d’adresse du père, souvent inutile car un appel exec() 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 le partage avec le fils. 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. |
Il est regrettable que Linux ait ressuscité ce spectre du passé. La page de manuel de BSD indique que cet appel système sera supprimé, et qu’il ne faut pas essayer de tirer profit du partage mémoire induit par vfork(). En théorie, la description standard ne nous autorise pas à utiliser vfork(), car l’appel exec() suivant peut échouer, et ce qui se produit ensuite est indéfini. Les détails de la gestion des signaux sont compliqués, et varient suivant les systèmes. Sous Linux (2.3.25) strace(1) ne peut pas suivre un appel vfork() et nécessite un patch du noyau. |
L’appel-système vfork() est apparu dans BSD 3.0. Dans BSD 4.4, il est devenu synonyme de fork(), mais NetBSD l’a réintroduit à nouveau. Sous Linux, il fut l’équivalent de fork() jusqu’au noyau 2.2.0-pre-6. Depuis le 2.2.0-pre-9 il s’agit d’un appel-système indépendant. Le support dans la bibliothèque a été introduit dans la GlibC 2.0.112. |
L’appel vfork() est assez similaire aux appels du même nom sous d’autres systèmes d’exploitation. Les contraintes que les standards apportent sur cet appel sont plus relâchées que celles sur fork(), 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’à un appel execve(), ou _exit(), ni sur le comportement de la mémoire partagée. |
clone(2), execve(2), fork(2), wait(2). |
Christophe Blaess, 1997. |
vfork(2) |