Quelle est la différence entre fork () et vfork ()?

13

Je voudrais comprendre en détail la différence entre fork () et vfork (). Je n'ai pas pu digérer complètement la page de manuel.

Je voudrais également clarifier le commentaire d'un de mes collègues " Dans Linux actuel, il n'y a pas de vfork (), même si vous l'appelez, il appellera en interne fork () ."

Sen
la source

Réponses:

24

Les pages de manuel sont généralement des documents de référence concis. Wikipédia est un meilleur endroit vers lequel se tourner pour des explications conceptuelles.

Fork duplique un processus: il crée un processus enfant qui est presque identique au processus parent (la différence la plus évidente est que le nouveau processus a un ID de processus différent). En particulier, fork (conceptuellement) doit copier toute la mémoire du processus parent.

Comme cela est plutôt coûteux, vfork a été inventé pour gérer un cas spécial commun où la copie n'est pas nécessaire. Souvent, la première chose que fait le processus enfant est de charger une nouvelle image de programme, c'est donc ce qui se passe:

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

L' execveappel charge un nouveau programme exécutable, qui remplace le code du processus et la mémoire de données par le code du nouvel exécutable et une nouvelle mémoire de données. Donc, la copie de mémoire entière créée par forkétait tout pour rien.

Ainsi l' vforkappel a été inventé. Il ne fait pas de copie de la mémoire. Par conséquent, vforkc'est bon marché, mais il est difficile à utiliser car vous devez vous assurer de ne pas accéder à la pile ou à l'espace de tas du processus dans le processus enfant. Notez que même la lecture pourrait être un problème, car le processus parent continue de s'exécuter. Par exemple, ce code est cassé (il peut ou non fonctionner selon que l'enfant ou le parent obtient d'abord une tranche de temps):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

Depuis l'invention de vfork, de meilleures optimisations ont été inventées. La plupart des systèmes modernes, y compris Linux, utilisent une forme de copie sur écriture , où les pages de la mémoire de processus ne sont pas copiées au moment de l' forkappel, mais plus tard lorsque le parent ou l'enfant écrit pour la première fois sur la page. C'est-à-dire que chaque page commence comme partagée et reste partagée jusqu'à ce que l'un des processus écrit sur cette page; le processus qui écrit obtient une nouvelle page physique (avec la même adresse virtuelle). La copie sur écriture rend vfork presque inutile, car forkil ne fera aucune copie dans les cas où il vforkserait utilisable.

Linux conserve vfork. L' forkappel système doit toujours faire une copie de la table de mémoire virtuelle du processus, même s'il ne copie pas la mémoire réelle; vforkn'a même pas besoin de faire ça. L'amélioration des performances est négligeable dans la plupart des applications.

Gilles 'SO- arrête d'être méchant'
la source
1
Merci pour cette brillante réponse. En faisant fork (), l'enfant va quand même obtenir un nouvel ID de processus et son espace virtuel associé, alors pourquoi devrait-il toujours faire une copie de la table de mémoire virtuelle du processus? Je ne suis pas clair dans cette partie.
Sen
@Sen: forkdoit créer un mappage de mémoire virtuelle distinct afin que les copies de copie sur écriture suivantes n'affectent qu'un seul des deux processus.
Gilles 'SO- arrête d'être méchant'
êtes-vous sûr que le processus parent est en cours d'exécution?
qbolec
2

Les appels système fork()et vfork()s sont différents.

L' fork()appel système génère deux processus identiques avec une mémoire distincte. L' vfork()appel système génère deux processus qui partagent la même mémoire.

Avec vfork()le parent attendra que l'enfant se termine. Le parent hérite des variables que le programme partage. Ainsi, après l'appel de l'enfant, toutes les variables modifiées à l'intérieur de l'enfant seront toujours modifiées à l'intérieur du parent.

Pour plus d'informations cliquez ici

Yogeesh HT
la source