• Aucun résultat trouvé

La hiérarchie de processus

Nous avons dit que la représentation d'un processus comportait trois composantes principales, le programme, les variables et l'état du processeur.

12.2.1. Un nombre fixe de processus banalisés

Certains systèmes créent, à l'initialisation, un nombre fixe de processus banalisés.

Ces processus peuvent être attachés chacun à un terminal particulier. Le programme du processus consiste alors en l'identification de l'usager (login) suivi de l'exécution de ses commandes et se termine par la remise dans l'état initial lors de la déconnexion (logout).

Gestion des processus

- 109 -

Ces processus peuvent être attachés à un terminal au moment de la demande de connexion depuis de terminal. Le programme est alors comparable au précédent. Le nombre de processus peut être inférieur au nombre de terminaux potentiels, entraînant un refus de connexion si aucun processus n'est disponible. Il est également possible d'allouer le processus à un couple de fichiers <entrée, sortie>, qui simulent le comportement d'un usager à son terminal, ce qui fournit une certaine forme de traitement par lot.

Ces processus peuvent être alloués à la demande pour une exécution d'une commande unique. Le programme, qui décrit leur comportement, est une boucle infinie qui consiste en l'attente d'une commande, suivie de son exécution. Suivant le cas, plusieurs processus pourront être alloués à un même usager en fonction de ses besoins. Cependant, il est nécessaire de disposer de plus de processus que dans les cas précédents, et la représentation de la partie propre de leur état occupe de la place en mémoire.

12.2.2. La création dynamique de processus

La création statique de processus banalisés présente l'inconvénient d'occuper de la place en mémoire, même lorsqu'ils ne sont pas utilisés. La deuxième méthode consiste à fournir une opération de création dynamique de processus ainsi qu'une opération de destruction de ces processus. Un telle opération de création doit permettre d'initialiser l'état du nouveau processus. Elle doit donc définir d'une part le programme (ou la suite d'instructions) décrivant l'activité du processus, ainsi que l'état initial de ses données, de ses variables et des registres du processeur. Elle doit donc se présenter sous la forme suivante:

id := créer_processus (programme, contexte)

où les paramètres définissent cet état initial. La valeur retournée éventuellement par cette opération permet d'identifier le processus qui a été ainsi créé. Cette dernière valeur n'a d'intérêt que si le processus créateur peut agir ultérieurement sur le processus créé au moyen d'autres opérations. La plupart des systèmes qui permettent la création dynamique de processus considèrent que la relation entre le processus créateur et le processus créé est importante, ce qui conduit à structurer l'ensemble des processus sous la forme d'un arbre, et à maintenir cette structure. Lors de la création de processus, le processus créé est relié automatiquement comme fils du processus créateur. Si un processus est détruit, on peut parcourir sa descendance pour la détruire au préalable. Lors de la fin d'exécution normale d'un processus P, deux solutions sont possibles:

La destruction de P n'est effective que lorsque tous ses fils sont eux-mêmes achevés. Ceci est

nécessaire lorsque le contexte initial du fils est inclus dans le contexte de P, puisque la destruction de celui-ci entraînerait la perte d'une partie du contexte du fils, et donc un déroulement anormal du processus fils s'il pouvait exister après la destruction de son père.

La destruction de P entraîne le rattachement de ses fils à l'un de ses ancêtres. Cependant comme

l'ascendance du processus P n'a pas de connaissance de ce qu'a fait P, on rattache souvent les fils soit au processus qui a initialisé le travail (login), soit à la racine qui est un processus standard et éternel.

12.2.3. L'exemple de Unix

Dans le système Unix, la création dynamique de processus est simplifiée à l'extrême, puisqu'il s'agit de créer un processus qui est une exacte copie de celui qui demande la création. Aucun paramètre n'est donc nécessaire, puisque le programme est le même, et que le système réalise une copie des données, variables et registres du processus demandeur pour créer le nouveau processus. La seule distinction entre le processus créateur et le processus créé, réside dans la valeur retournée par la fonction de création. Le processus créateur reçoit l'identité du processus créé, alors que ce dernier reçoit la valeur 0. Par ailleurs, le système structure les processus en arbre. Considérons le petit morceau de programme suivant:

id_fils := fork (); { création du fils }

si id_fils = 0 alors { il s'agit du processus fils }

sinon { il s'agit du processus père }

La fonction fork () crée le processus fils comme copie conforme du processus père. Les deux

Environnement physique

- 110 -

zones de données et de variables identiques à ce moment. La mémorisation du résultat dans la variable id_fils signifie la mémorisation dans un emplacement mémoire propre à chacun d'eux.

Notons que, puisque le fils obtient une copie des données du père, celui-ci peut lui transmettre tout ce qu'il désire à ce moment. Par la suite, les deux processus sont effectivement indépendants et n'ont pas de données communes à l'exception des objets externes.

Si le processus père se termine avant le processus fils, le fils est rattaché au processus racine de façon à conserver la structure d'arbre. Le processus père peut attendre la terminaison d'un de ses fils par la fonction (en langage C):

id_fils := wait (&status);

qui retourne le numéro d'un processus fils qui est terminé, en mettant dans la variable status un

code indiquant la façon dont ce processsus s'est terminé. Si aucun fils n'est terminé alors qu'il y en a encore d'actifs, le processus père est mis en attente d'une terminaison de l'un de ses fils. S'il n'y a plus de processus fils, la fonction retourne la valeur -1.

Par ailleurs le système Unix fournit une fonction exec qui permet à un processus de changer le

programme en cours d'exécution. Cette fonction n'affecte évidemment que le processus demandeur. Elle change l'état du processus en remplaçant le code des instructions, en supprimant les données, variables et registres qui étaient relatifs à l'ancien programme et en les initialisant pour le nouveau. La combinaison de la fonction fork et de cette fonction exec par le processus fils permet de réaliser

la fonction créer_processus mentionnée ci-dessus.