Pourquoi le mécanisme de création de processus par défaut est-il un fork?

46

Fork (), l’appel système UNIX pour la création de processus, crée un processus enfant en copiant le processus parent. D'après ce que je comprends, ceci est presque toujours suivi d'un appel à exec () pour remplacer l'espace mémoire du processus enfant (segment de texte compris). Copier l'espace mémoire du parent dans fork () m'a toujours semblé inutile (bien que je sache que le gaspillage peut être minimisé en faisant une copie sur écriture des segments de mémoire, de sorte que seuls les pointeurs soient copiés). Quoi qu'il en soit, quelqu'un sait-il pourquoi cette approche de duplication est requise pour la création de processus?

Ellen Spertus
la source
3
Notez que la fork(2)page de manuel sous Linux indique: Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child. J'imagine (mais je ne le sais pas avec certitude) que c'est le cas pour d'autres versions Unix modernes.
larsks
4
L’original, PDP-11 Unix, copiait réellement tous les octets d’un processus "forké": mais il ne disposait que de 64 Ko d’exécutable et d’au plus 64 Ko de données; devinez que CHAQUE UNIX et UNIX-like-like depuis environ 1990 a eu des segments de texte de copie sur écriture, donc je ne suis même pas sûr de savoir pourquoi les livres et les articles propagent désormais "problème de performance avec fork".
Bruce Ediger
De nos jours, fork est implémenté de la même manière que vfork ( openbsd.org/cgi-bin/… ). C'est efficace, ne vous inquiétez pas.
Aki
Notez également qu'il y a beaucoup d'utilisations pour lesquelles vous n'exécutez pas après un fork (ou du moins, n'exécutez pas immédiatement): pensez aux tuyaux et aux serveurs Web.
Jfg956
Vous pouvez penser que ce serait lent. Mais comme @cjm indique que Microsoft utilise alternativement CreateProcess, ils ont dû implémenter les threads tôt (peut-être la seule chose sur laquelle ils mènent), car CreateProcess est lent. (Ils avaient aussi besoin de threads car ils selectétaient cassés, mais c'est une autre histoire).
ctrl-alt-delor

Réponses:

57

C'est pour simplifier l'interface. L’alternative à forket execressemblerait à la fonction CreateProcess de Windows . Notez combien de paramètres CreateProcessont, et beaucoup d’entre eux sont des structures avec encore plus de paramètres. En effet, tout ce que vous souhaitez contrôler sur le nouveau processus doit être transmis CreateProcess. En fait, le nombre de CreateProcessparamètres étant insuffisant, Microsoft a donc dû ajouter CreateProcessAsUser et CreateProcessWithLogonW .

Avec le fork/execmodèle, vous n'avez pas besoin de tous ces paramètres. Au lieu de cela, certains attributs du processus sont préservés exec. Cela vous permet de forkmodifier les attributs de processus de votre choix (en utilisant les mêmes fonctions que vous utiliseriez normalement), puis exec . Sous Linux, forkn’a pas de paramètre et execven’a que 3: le programme à exécuter, la ligne de commande à lui donner et son environnement. (Il existe d'autres execfonctions, mais ce ne sont que des wrappers execvefournis par la bibliothèque C pour simplifier les cas d'utilisation courants.)

Si vous voulez commencer un processus avec un autre répertoire courant: fork, chdir, exec.

Si vous souhaitez rediriger stdin / stdout: fork, fichiers ouverture / fermeture, exec.

Si vous voulez les utilisateurs du commutateur: fork, setuid, exec.

Toutes ces choses peuvent être combinées au besoin. Si quelqu'un propose un nouveau type d'attribut de processus, vous n'avez pas à changer forket exec.

Comme mentionné ci-dessus, la plupart des Unix modernes utilisent la copie sur écriture, ce forkqui ne nécessite pas de temps système important.

cjm
la source
16
Excellente explication. "Ceux qui ne comprennent pas UNIX sont condamnés à le réinventer, mal." - Henry Spencer
Kyle Jones
1
Merci! Avez-vous une référence, par hasard?
Ellen Spertus
1
@Aki, nope, CreateProcess () crée littéralement un nouveau processus et le construit à partir de rien, sans forking.
Psusi
2
Mais ne doit-il pas y avoir un équivalent de CreateProcess () quelque part dans Unix? Sinon, comment le tout premier processus est-il créé? Contrairement à un dieu créateur de mythologie, le premier processus ne peut pas déborder () du néant. ;-)
Steven lundi
2
@StevenMonday, oui, mais c'est dans le code d'initialisation du noyau et non accessible de l'extérieur. Il n'a pas besoin de tous ces paramètres car presque tout est codé en dur. Il ne peut créer que le processus ID 1, également appelé processus init. Après cela, les processus sont créés uniquement par forgeage.
cjm
5

En plus de la réponse de cjm, la spécification Single Unix définit une fonction nommée vfork(). Cette fonction fonctionne comme un fork, sauf que le processus fork a un comportement indéfini s'il ne fait rien d'autre qu'appeler une fonction de la famille exec ou un appel _exit().

Ainsi, à peu près, la seule utilisation avec un comportement défini est:

pid_t ret = vfork();
if(ret == 0)
{
    exec(...);
    _exit(EXIT_FAILURE); //in case exec failed for any reason.
}

Alors, que fait vfork-on? C'est peu coûteux fork. Dans les implémentations sans copie sur écriture, le processus résultant partagera de l'espace mémoire avec le processus d'origine (d'où le comportement indéfini). Dans les implémentations avec copie sur écriture, il vforkest permis d’être identique à fork(), étant donné que les implémentations de copie sur écriture sont rapides.

Il existe également une posix_spawnfonction optionnelle (et une posix_spawnpfonction) permettant de créer directement un nouveau processus. (Il est également possible de les implémenter avec un appel de bibliothèque utilisant forket exec, et un exemple d'implémentation est fourni.)

Kevin Cathcart
la source