Quelle est la différence entre fork() et vfork()?
6 réponses
le but de vfork
était d'éliminer le coût de copie de l'image complète du procédé si vous voulez seulement faire un exec*
dans l'enfant. Parce que exec*
remplace l'image entière du processus enfant, il n'y a aucun intérêt à copier l'image du parent.
if ((pid = vfork()) == 0) {
execl(..., NULL); /* after a successful execl the parent should be resumed */
_exit(127); /* terminate the child in case execl fails */
}
Pour d'autres types d'utilisations, vfork
est dangereux et imprévisible.
avec la plupart des noyaux actuels, cependant, y compris Linux, le principal avantage de vfork
a disparu en raison de la façon dont fork
est mis en œuvre. Plutôt que de copier l'image entière lorsque fork
est exécuté, des techniques de copie-sur-écriture sont utilisées.
comme déjà indiqué, la page de manuel vfork
est claire sur les différences.
Ce thème donne une bonne description de fork
, vfork
, clone
et exec
.
ci-dessous sont quelques différences souvent négligées entre fork
et vfork
j'ai expérimenté sur certains Linux 2.6.3 x systèmes embarqués, j'ai travaillé avec.
même avec la copie-sur-Écrire des techniques, fork
échoue si vous n'avez pas assez de mémoire pour dupliquer la mémoire utilisée par le processus parent. Par exemple, si le processus parent utilise 2 Go de mémoire résidente (c'est-à-dire de mémoire qui est utilisée et pas seulement attribuée), fork
échoue si vous avez moins de 2 Go de mémoire libre. C'est frustrant quand vous voulez juste exec
un programme simple et donc n'aura jamais besoin de cet espace d'adresse parent énorme!
vfork
n'a pas ce problème de mémoire, car il ne duplique pas le espace d'adresse des parents. Le processus enfant agit plus comme un fil dans lequel vous pouvez appeler exec*
ou _exit
sans nuire à votre processus parent.
parce que les tables de page de mémoire ne sont pas dupliquées, vfork
est beaucoup plus rapide que fork
et vfork
le temps d'exécution de" n'est pas affecté par la quantité de mémoire que le processus parent utilise, comme souligné ici: http://blog.famzah.net/2009/11/20/fork-gets-slower-as-parent-process-use-more-memory/
dans les situations où les performances sont critiques et/ou limitées en mémoire, vfork
+ exec*
peut donc être une bonne alternative à fork
+ exec*
. Le problème est qu'il est moins sûr et la page de man dit vfork
est susceptible de devenir obsolète dans l'avenir.
une solution plus sûre et plus portable peut être de regarder la fonction posix_spawn
, qui est de niveau supérieur et offre plus d'options. Il utilise en toute sécurité vfork
lorsque possible, en fonction des options que vous lui passez. J'ai été en mesure d'utiliser posix_spawn
avec succès et surmonter ce problème ennuyeux "double vérification de mémoire" que fork
+ exec
me donnait.
une très bonne page sur ce sujet, avec des liens vers des exemples posix_spawn
.
De ma page de manuel de
(de POSIX.1) la fonction vfork () a le même effet que la fourchette(2), sauf que le comportement est indéfini si l' processus créé par vfork () modifie une donnée autre qu'une variable de type pid_t utilisé pour stocker la valeur de retour de vfork(), ou des retours de la fonction dans laquelle vfork() a été appelé, ou appelle toute autre fonction avant d'appeler avec succès _exit(2) ou l'un des exec(3) de la famille des fonction.
vfork () diffère de fork (2) en que le parent est suspendu jusqu'à ce que le enfant prend fin (normalement, par appeler _exit(2), ou anormalement, après la livraison d'un signal fatal), ou il fait un appel à execve (2). Jusqu'à ce point, la l'enfant partage toute sa mémoire avec sa société mère, y compris la pile. L'enfant ne doit pas retourner de la fonction courante ou la sortie d'appel(3), mais peut appeler _exit(2).
certains systèmes ont un système appelé vfork (), qui a été initialement conçu comme une version de fork (). Puisque fork () impliquait de copier la totalité de l'espace d'adresse du processus, et était donc assez cher, la fonction vfork() a été introduite (en 3.0 BSD).
cependant, depuis l'introduction de vfork (), la mise en œuvre de fork() s'est considérablement améliorée, notamment avec l'introduction de `copy-on-write', où la copie de l'adresse du processus l'espace est simulé de façon transparente en permettant aux deux processus de se référer à la même mémoire physique jusqu'à ce que l'un d'eux la modifie. Cela supprime en grande partie la justification de vfork(); en effet, une grande partie des systèmes ne disposent plus de la fonctionnalité d'origine de vfork. vfork() complètement. Pour la compatibilité, cependant, il peut encore y avoir un appel vfork() présent, qui appelle simplement fork() sans tenter d'émuler toute la sémantique de vfork ().
en conséquence, il est très imprudent de utilisez en fait l'une des différences entre fork() et vfork(). En effet, il est sans doute imprudent d'utiliser vfork (), sauf si vous savez exactement pourquoi vous le souhaitez.
la différence fondamentale entre les deux est que lorsqu'un nouveau processus est créé avec vfork(), le processus parent est temporairement suspendu, et le processus enfant peut emprunter l'espace d'adresse du parent. Cet étrange état de choses continue jusqu'à ce que le processus de l'enfant soit sort, soit appelle execve (), auquel le processus parent continue.
cela signifie que le processus enfant d'une vfork() doit être prudent pour éviter de modifier de façon inattendue les variables du processus parent. En particulier, le processus enfant ne doit pas revenir de la fonction contenant l'appel vfork (), et il ne doit pas appeler exit() (s'il doit sortir, il doit utiliser _exit(); en fait, ceci est également vrai pour l'enfant d'un fork normal()).
la différence fondamentale entre les deux est que lorsqu'un nouveau processus est créé avec vfork()
, le processus parent est temporairement suspendu, et le processus enfant peut emprunter l'espace d'adresse du parent. Cette situation étrange se poursuit jusqu'à ce que le processus de l'enfant cesse, ou appelle execve()
, et que le processus parental se poursuive.
cela signifie que le processus enfant d'un vfork()
doit être prudent de
évitez de modifier de façon inattendue les variables du processus parent. Dans
en particulier, le processus de l'enfant ne doit pas revenir de la fonction
contenant l'appel vfork()
, et il ne doit pas appeler
exit()
(si elle doit sortir, elle doit utiliser _exit();
en fait, cela est également vrai pour l'enfant à la normale fork()
).
cependant, depuis que vfork()
a été introduit, le
la mise en œuvre de fork()
s'est considérablement améliorée, notamment
avec l'introduction de "copie à l'écriture", de où la copie de la
processus l'espace d'adresse est truqué de manière transparente en permettant les deux processus
pour faire référence à la même mémoire physique jusqu'à ce que l'un d'eux modifie
il. cela supprime largement la justification de vfork();
en effet, un
une grande partie des systèmes ne disposent plus de la fonctionnalité d'origine
vfork()
complètement. Pour la compatibilité, cependant, il peut encore y avoir
un vfork()
appel présent, qui appelle simplement fork()
sans
tenter pour imiter toute la sémantique vfork()
.
en conséquence, il est très imprudent de faire usage de l'un des
différences entre fork()
et vfork()
. En effet, il est
probablement pas sage d'utiliser vfork()
du tout, sauf si vous savez exactement
pourquoi vous le souhaitez.