Quelle est la différence entre la fourche () et vfork ()?
La solution
Le but de vfork
était d'éliminer les frais généraux de copie toute l'image de processus si vous voulez seulement faire une exec*
chez l'enfant. Parce que exec*
remplace l'image entière du processus de l'enfant, il n'y a pas de point à 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 les 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 à cause de la façon dont fork
est mis en œuvre. Plutôt que de copier l'image entière lorsque fork
est exécutée, les techniques sont utilisées copy-on-write.
Autres conseils
Comme nous l'avons dit, la page de manuel vfork
est clair sur les différences.
Ce sujet donne une bonne description de fork
, vfork
, clone
et exec
.
Voici quelques différences entre souvent négligé fork
et je vfork
expérimenté sur des systèmes embarqués Linux 2.6.3x avec lesquels je travaillais.
Même avec des techniques de copie en écriture, fork
échoue si vous ne disposez pas de suffisamment 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 (mémoire qui est utilisée et non seulement alloué), fork
échoue si vous avez moins de 2 Go de mémoire libre. Ce qui est frustrant quand vous voulez juste exec
un programme simple et donc aurez jamais besoin que grand espace d'adressage parent!
vfork
n'a pas ce problème de mémoire, car il ne fait pas double l'espace d'adressage mère. Le processus d'enfant agit plus comme un fil dans lequel vous pouvez appeler exec*
ou _exit
sans nuire à votre processus parent.
Comme les tables de page de mémoire ne sont pas dupliqués, vfork
est beaucoup plus rapide que fork
et le temps d'exécution de vfork
ne sont pas affectées par la quantité de mémoire les utilisations processus parent, comme l'a souligné ici: http://blog.famzah.net/2009/11/20 / fourche obtient-lente comme parent-process-utilisation-plus-mémoire /
Dans les situations où la performance est critique et / ou une mémoire limitée, vfork
+ exec*
peut donc être une bonne alternative à fork
+ exec*
. Le problème est qu'il est moins sûr et la page de manuel dit vfork
est susceptible de devenir dépréciée dans l'avenir.
Une solution plus sûre et plus portable peut être à regarder la fonction posix_spawn
, ce qui est de niveau et offre plus d'options plus. Il en toute sécurité les utilisations vfork
lorsque cela est possible, en fonction des options que vous passer. Je suis en mesure d'utiliser posix_spawn
avec succès et surmonter cette ennuyeux « numéro double vérification de la mémoire » qui fork
+ exec
me donnait.
Une page vraiment bien sur ce sujet, avec des liens vers certains Exemples posix_spawn
.
De ma page man
(De POSIX.1) La fonction vfork () a le même effet que la fourche (2), à l'exception que le comportement est indéfini si la processus créé par vfork () soit modifie des données autres qu'une variable de type pid_t utilisé pour stocker la valeur de retour de vfork () ou le retour de la fonction dans laquelle vfork () a été appelé ou appelle une autre fonction avant d'appeler avec succès _exit (2) ou l'un de la famille exec (3) de fonctions.
vfork () diffère de la fourche (2) que le parent est suspendu jusqu'à ce que le enfant (soit normalement se termine, par _exit appelant (2), ou anormalement, après la livraison d'un signal fatal), ou effectue un appel à execve (2). Jusqu'à ce moment-là, la enfant partage tout avec mémoire son parent, y compris la pile. L'enfant ne doit pas revenir de la fonction en cours ou à la sortie d'appel (3), mais peut appeler _exit (2).
Certains systèmes ont un vfork d'appel système (), qui a été conçu à l'origine comme une version moins en tête de fourche (). Depuis fork () impliqués copier l'espace d'adressage ensemble du processus, et était donc assez cher, la fonction vfork () a été introduit (dans BSD 3.0).
Cependant, depuis vfork () a été introduite, la mise en œuvre de la fourche () a amélioré considérablement, notamment avec l'introduction de `copy-on-write », où la copie de l'espace d'adressage du processus est truqué de manière transparente en permettant à la fois processus de se référer à la même mémoire physique jusqu'à ce que l'un d'eux le modifier. Cela supprime en grande partie la justification de vfork (); En effet, une grande partie des systèmes manquent maintenant la fonctionnalité originale de vfork () complètement. Pour la compatibilité, cependant, il peut y avoir encore un vfork () présent appel, qui appelle simplement la sémantique fork () sans essayer d'imiter tous les vfork ().
Par conséquent, il est très imprudent de faire réellement usage de l'une des différences entre fork () et vfork (). En effet, il est probablement imprudent d'utiliser vfork () du tout, à moins que vous savez exactement pourquoi vous voulez.
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 de l'enfant peut emprunter l'espace d'adressage du parent. Cet état étrange des affaires se poursuit jusqu'à ce que le processus enfant soit les sorties, ou des appels execve (), point auquel le processus parent se poursuit.
Cela signifie que le processus d'enfant d'un vfork () doit être prudent pour ne pas modifier de façon inattendue les variables du processus parent. En particulier, le processus de l'enfant ne doit pas revenir de la fonction contenant le vfork () appel, et il ne doit pas appeler exit () (si elle a besoin pour sortir, il doit utiliser _exit (), en fait, cela est également vrai pour l'enfant d'une fourchette normale ()).
et wikipedia -
Sur certains systèmes, vfork () est le même comme fork (). La fonction vfork () diffère de la fourche () uniquement en ce que le processus enfant peut de partager le code et les données le processus appelant (parent processus).
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 de l'enfant peut emprunter l'espace d'adressage du parent. Cet état étrange des affaires se poursuit jusqu'à ce que le processus de l'enfant soit des sorties, ou appelle execve()
, à quel point le processus parent continue.
Cela signifie que le processus d'enfant d'un vfork()
doit faire attention à
ne pas modifier de façon inattendue les variables du processus parent. Dans
notamment, le processus d'enfant ne doit pas revenir de la fonction
contenant l'appel vfork()
, et il ne doit pas appeler
exit()
(si elle a besoin pour sortir, il doit utiliser _exit();
En fait, cela est également vrai pour l'enfant d'un fork()
normal).
Cependant, depuis vfork()
a été introduit, la
la mise en œuvre de fork()
a amélioré considérablement, notamment
avec l'introduction de 'copy-on-write', où la copie du
l'espace d'adressage du processus est simulé de façon transparente par les deux procédés permettant
de se référer à la même mémoire physique jusqu'à ce que soit de les modifier
il. Cela supprime en grande partie la justification de vfork();
en effet, un
grande partie des systèmes manquent maintenant la fonctionnalité originale de
vfork()
complètement. Pour la compatibilité, cependant, il peut y avoir encore
un présent appel vfork()
, qui appelle simplement fork()
sans
tenter d'imiter l'ensemble de la sémantique vfork()
.
Par conséquent, il est très imprudent de faire réellement usage de l'un des
les différences entre fork()
et vfork()
. En effet, ça l'est
probablement pas sage d'utiliser vfork()
du tout, à moins que vous savez exactement
pourquoi vous voulez.