Question

Quelle est la différence entre fork() et vfork() ? Est-ce vfork() retour comme fork().

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top