Sous Unix, chaque fois que nous souhaitons créer un nouveau processus, nous découpons le processus actuel en créant un nouveau processus enfant identique au processus parent. nous faisons ensuite un appel système exec pour remplacer toutes les données du processus parent par celles du nouveau processus.
Pourquoi crée-t-on une copie du processus parent au départ sans créer directement un nouveau processus?
process
architecture
fork
sarthak
la source
la source
Réponses:
La réponse courte est:
fork
est sous Unix parce qu’il était facile de s’intégrer au système existant à l’époque et qu’un système précédent à Berkeley avait utilisé le concept de fourches.De L'évolution du système de partage du temps Unix (le texte pertinent a été mis en évidence ):
Depuis cet article, Unix a évolué.
fork
suivi deexec
n’est plus le seul moyen d’exécuter un programme.vfork a été créé pour être un fork plus efficace dans le cas où le nouveau processus a l'intention de faire un exec juste après le fork. Après avoir effectué une vfork, les processus parent et enfant partagent le même espace de données et le processus parent est suspendu jusqu'à ce que le processus enfant exécute un programme ou se ferme.
posix_spawn crée un nouveau processus et exécute un fichier en un seul appel système. Il faut un tas de paramètres qui vous permettent de partager de manière sélective les fichiers ouverts de l'appelant et de copier sa disposition du signal et d'autres attributs dans le nouveau processus.
la source
posix_spawn()
effectuer les mêmes tâches de replomberie après branchement, qui peuvent être facilement effectuées à l'aide d'unfork()
code en ligne, constituent un argument convaincant en faveur d'fork()
une utilisation beaucoup plus simple.[Je vais répéter une partie de ma réponse à partir d' ici .]
Pourquoi ne pas simplement avoir une commande qui crée un nouveau processus à partir de zéro? N'est-il pas absurde et inefficace d'en copier un qui ne sera remplacé que tout de suite?
En fait, cela ne serait probablement pas aussi efficace pour plusieurs raisons:
La « copie » produit par
fork()
est un peu une abstraction, car le noyau utilise une copie sur écriture du système ; tout ce qui doit être créé est une carte mémoire virtuelle. Si la copie appelle alors immédiatementexec()
, la plupart des données qui auraient été copiées si elles avaient été modifiées par l'activité du processus ne doivent jamais être copiées / créées car le processus ne nécessite aucune utilisation.Divers aspects significatifs du processus enfant (par exemple son environnement) ne doivent pas nécessairement être dupliqués individuellement ou définis en fonction d'une analyse complexe du contexte, etc. Ils sont simplement supposés être identiques à ceux du processus appelant. c'est le système assez intuitif que nous connaissons.
Pour expliquer # 1 un peu plus loin, la mémoire qui est "copiée" mais jamais accédée par la suite n’est jamais vraiment copiée, du moins dans la plupart des cas. Une exception dans ce contexte pourrait être si vous avez créé un processus, puis le processus parent s'est terminé avant que l'enfant ne se remplace lui-même
exec()
. Je dis pourrait parce qu'une grande partie du parent pourrait être mise en cache si la mémoire disponible est suffisante et je ne sais pas dans quelle mesure cela serait exploité (ce qui dépendrait de la mise en œuvre du système d'exploitation).Bien sûr, cela ne rend pas à première vue l'utilisation d'une copie plus efficace que celle d'une ardoise vierge - sauf que "l'ardoise vierge" n'est pas littéralement rien, et doit impliquer une attribution. Le système pourrait avoir un modèle de processus vierge / nouveau, générique, qu'il copie de la même manière 1, mais qui ne sauvegarderait alors rien, par rapport à la fourchette de copie sur écriture. Donc, n ° 1 démontre simplement que l'utilisation d'un "nouveau" processus vide ne serait pas plus efficace.
Le point 2 explique pourquoi l'utilisation de la fourche est probablement plus efficace. L'environnement d'un enfant est hérité de son parent, même s'il s'agit d'un exécutable complètement différent. Par exemple, si le processus parent est un shell et l’enfant, un navigateur Web,
$HOME
reste identique pour les deux, mais puisque l’un ou l’autre pourrait le changer par la suite, il doit s'agir de deux copies distinctes. Celui de l'enfant est produit par l'originalfork()
.1. Une stratégie qui n'a peut-être pas beaucoup de sens littéral, mais ce que je veux dire, c'est que créer un processus implique plus que copier son image dans la mémoire à partir d'un disque.
la source
fork()
peut le faire très rapidement (comme l'a mentionné GL, de l'ordre de 27 lignes de montage). Si vous voulez créer un processus en partant de zéro, celafork()
ne coûte qu'un tout petit peu plus que de partir d'un processus créé vide (27 lignes d'assemblage + coût de la fermeture des descripteurs de fichiers). Doncfork
gère à la fois fork et créer bien, alors quecreate
peut seulement gérer créer bien.fork
copiez en fait toute la mémoire de processus et cela coûtait très cher.Je pense que la raison pour laquelle Unix n'avait que la
fork
fonction de créer de nouveaux processus est le résultat de la philosophie UnixIls construisent une fonction qui fait une chose bien. Cela crée un processus enfant.
Ce que l’on fait avec le nouveau processus appartient alors au programmeur. Il peut utiliser l'une des
exec*
fonctions et lancer un programme différent, ou il ne peut pas utiliser exec et utiliser les deux instances du même programme, ce qui peut être utile.Donc, vous obtenez un plus grand degré de liberté puisque vous pouvez utiliser
et en plus vous suffit de mémoriser les
fork
et lesexec*
appels de fonction, que vous deviez faire dans les années 1970.la source
Il existe deux philosophies de création de processus: fourchette avec héritage et création avec arguments. Unix utilise fork, évidemment. (OSE, par exemple, et VMS utilisent la méthode create.) Unix a BEAUCOUP de caractéristiques pouvant être héritées, et d'autres sont ajoutées périodiquement. Par héritage, ces nouvelles caractéristiques peuvent être ajoutées SANS MODIFIER LES PROGRAMMES EXISTANTS! À l'aide d'un modèle de création avec arguments, l'ajout de nouvelles caractéristiques signifierait l'ajout de nouveaux arguments à l'appel de création. Le modèle Unix est plus simple.
Il offre également le modèle très utile fork-without-exec, dans lequel un processus peut se diviser en plusieurs parties. Cela était essentiel à l'époque où il n'existait aucune forme d'E / S asynchrone, ce qui est utile pour tirer parti de plusieurs processeurs dans un système. (Pré-discussions.) J'ai souvent fait cela au fil des ans, même récemment. En substance, cela permet de conteneuriser plusieurs "programmes" dans un seul programme, de sorte qu'il n'y a absolument aucune place pour la corruption ou les asymétries de version, etc.
Le modèle fork / exec permet également à un enfant spécifique d'hériter d'un environnement radicalement étrange, configuré entre le fork et l'exec. Des choses comme les descripteurs de fichiers hérités, en particulier. (Une extension de stdio fd.) Le modèle de création n'offre pas la possibilité d'hériter de tout ce qui n'a pas été envisagé par les créateurs de l'appel de création.
Certains systèmes peuvent également prendre en charge la compilation dynamique de code natif, où le processus écrit son propre programme de code natif. En d'autres termes, il veut un nouveau programme qu'il écrit lui-même à la volée, SANS passer par le cycle du code source / compilateur / éditeur de liens et occupant de l'espace disque. (Je pense qu’il existe un système de langage Verilog qui le fait.) Le modèle fork prend en charge cela, mais pas le modèle create.
la source
La fonction fork () ne sert pas uniquement à copier le processus père, elle renvoie une valeur indiquant que le processus est le processus père ou fils, l'image ci-dessous explique comment utiliser four () comme père et fils:
comme indiqué lorsque le processus est le père fork () renvoie l'ID du processus fils,
PID
sinon il retourne0
par exemple, vous pouvez l'utiliser si vous avez un processus (serveur Web) qui reçoit les demandes et à chaque demande, il crée un
son process
processus pour traiter cette demande, ici le père et ses fils ont des emplois différents.SO, pas d'exécuter une copie d'un processus n'est pas la chose exacte comme fork ().
la source
fork
si vous supposez que vous voulezfork
en premier lieuLa redirection d'E / S est plus facilement implémentée après fork et avant exec. L'enfant, sachant que c'est l'enfant, peut fermer les descripteurs de fichier, en ouvrir de nouveaux, dup () ou dup2 () pour les placer sur le bon numéro fd, etc., sans affecter le parent. Après cela, et éventuellement toute modification de la variable d’environnement souhaitée (n’affectant pas non plus le parent), il peut exécuter le nouveau programme dans l’environnement sur mesure.
la source
Je pense que tout le monde ici sait que fork fonctionne, mais la question est de savoir pourquoi nous devons créer une copie exacte du parent en utilisant fork. Réponse ==> Prenons un exemple de serveur (sans fork), pendant que le client-1 accède au serveur, si le deuxième client-2 est arrivé en même temps et veut accéder au serveur mais le serveur ne donne pas l’autorisation aux nouveaux arrivés. client-2 parce que le serveur est occupé à servir le client-1, le client-2 doit donc attendre. Une fois que tous les services du client-1 sont terminés, le client-2 est maintenant en mesure d'accéder au serveur.Maintenant, considérez si client-3 arrive, le client-3 doit donc attendre que tous les services du client-2 soient terminés. Prenez le scénario où des milliers de clients doivent accéder au serveur en même temps ... puis tous les clients doivent attendez (le serveur est occupé !!).
Ceci est évité en créant (à l'aide de fork) une copie exacte en double (par exemple, enfant) du serveur, où chaque enfant (copie exacte en double de son serveur parent) est dédié au client nouvellement arrivé, de sorte que tous les clients accèdent simultanément au même serveur. serveur.
la source
fork
appel qui copie le processus parent est qu'il n'est pas nécessaire de disposer de deux programmes distincts - mais le fait de disposer de programmes distincts (par exemple,inetd
) peut rendre le système plus modulaire.