Systèmes d’Exploitations Avancés

Programming, Math, etc. · course

Voir tous les documents en systèmes d'exploitation et cloud

##### Systèmes d’Exploitations Avancés Chapitre II : Gestion des Processus et Threads Amine DHRAIEF Mastère professionnel en Modélisation, Bases de Données et Intégration des Systèmes ESEN, Univ. Manouba Introduction Les premiers S.E autorisaient un seul programme à être exécuter à la fois. Un tel programme avait un contrôle complet du système et un accès à toutes les ressources du système Les S.E actuels permettent à plusieurs programme s d'être charger en mémoire et exécuter en même temps. Cette évolution a nécessité un contrôle plus strict et un cloisonnement plus rigoureux des différents programmes. Introduction Ces besoins ont conduit à la création de la notion de processus , qui est un « programme en exécution » . Un processus est l'unité fondamental dans le cadre d’un S.E moderne temps partagé. Un système se compose d'un ensemble de processus: Les processus du S.E exécutent le code du S.E et des processus utilisateurs exécutent le code de l'utilisateur. Tous ces processus peuvent s'exécuter en même temps. En commutant le processeur entre les processus, le système d‘exploitation peut rendre l'ordinateur plus productif. Le Concept de Processus Un processus est souvent définit comme étant un programme en exécution. - Un **processus** est plus **que le code du programme (** _**text section**_ **)** Un processus inclus une représentation de l'activité en cours du programme : - Le **contenu des registres du processeur.** - Le _**program counter**_ (PC) (un registre qui contient l’adresse mémoire de l’instruction en cours ) Un processus comprend également une pile d’exécution qui contient des données provisoires (tels que la fonction, les paramètres, des adresses de retour, et les variables locales), et une section de données ( data section ), qui contient les variables globales. Un processus peut également comprendre un tas ( heap ) qui est un mémoire allouée dynamiquement lors de l'exécution processus. LE CONCEPT DE PROCESSUS 30/09/2016 Systèmes d'Exploitation Avancés 5 Le Concept de Processus 30/09/2016 Systèmes d'Exploitation Avancés 6 Le Concept de Processus Programme vs. Processus Le programme n'est pas en soi un processus, un programme est une entité passive , comme un fichier contenant une liste d'instructions stockées sur le disque (souvent appelé un fichier exécutable), alors qu'un processus est une entité active , avec un programme countrer spécifiant la prochaine instruction à exécuter et un ensemble de ressources associées. Un programme devient un processus lorsqu'un fichier exécutable est chargé en mémoire . Même si deux processus peuvent être associés à un même programme, ils sont néanmoins considérés comme deux séquences d'exécution séparées . Par exemple, plusieurs utilisateurs peuvent exécuter différentes copies du logiciel de courrier électronique. Chacune d'elles est un processus distinct, et bien que les sections de texte sont équivalentes, les data section, la pile, le heap sont différents. 30/09/2016 Systèmes d'Exploitation Avancés 7 Le Concept de Processus Les états d’un processus Durant son exécution, un processus change d’état Chaque processus peut être dans l'un des états suivants: New: Le processus est en cours de création. Running : Les instructions sont en cours d'exécution. Waiting : Le processus est en attente d'un événement de se produire (par exemple une E / S, l'achèvement ou la réception d'un signal). Ready : Le processus est en attente d'affectation à un processeur. Terminated : Le processus a fini d'exécution 30/09/2016 Systèmes d'Exploitation Avancés 8 Le Concept de Processus Les états d’un processus 30/09/2016 Systèmes d'Exploitation Avancés 9 Le Concept de Processus Process Control Block Chaque processus est représenté dans le système d'exploitation par un bloc de contrôle de processus ( Process Control Block - PCB ) appelé aussi un task-control block Le système d’exploitation maintient dans une table appelée « table des processus » - les informations sur tous les processus créés (une entrée par processus : PCB). 30/09/2016 Systèmes d'Exploitation Avancés 10 Le Concept de Processus Process Control Block 30/09/2016 Systèmes d'Exploitation Avancés 11 Le Concept de Processus Process Control Block L’état du processus : L'état peut être New, Ready, Running, Waiting,… Program counter: Le compteur indique l'adresse de l'instruction suivante à exécuter pour le processus. Les registres CPU: Les registres varient en nombre et en type, en fonction de l'architecture informatique. Ils comprennent les accumulateurs, les registres d'index, pointeurs de pile et les registres à usage général ces registres doivent être sauvegardé si une interruption se produit, pour permettre au processus de se poursuivre correctement par la suite 30/09/2016 Systèmes d'Exploitation Avancés 12 Le Concept de Processus Process Control Block Les informations relatives à l’ordonnancement du CPU: Comprennent la priorité du processus, les pointeurs vers des files d'attente d'ordonnancement, et les autres paramètres d'ordonnancement. Les Informations relatives à la gestion de la mémoire: Ces informations peuvent inclure les tables de page, les tables de segments… Les informations d'état des E/S: Comprend la liste des périphériques E/S allouée au processus, la liste de fichiers ouverts, … 30/09/2016 Systèmes d'Exploitation Avancés 13 Le Concept de Processus Process Control Block 30/09/2016 Systèmes d'Exploitation Avancés 14 Le Concept de Processus Process Control Block Dans le système d'exploitation Linux, le PCB est représenté par la structure C task_struct . Cette structure contient toutes les informations nécessaires l'information de représentation d'un processus: - L'état du processus - son ordonnancement - la gestion de mémoire - la liste des fichiers ouverts - et pointeurs vers le processus parent et l'un de ses enfants. - Parent d'un processus est le processus qui l'a créé; - ses enfants sont tous les processus qu'il crée 30/09/2016 Systèmes d'Exploitation Avancés 15 Le Concept de Processus Process Control Block Quelques champ de la task_struct (/linux/sched.h) (http://lxr.linux.no/#linux+v3.5.4/include/linux/sched.h#L 1229) pid_t pid; /* process identifier / long state; / state of the process / unsigned int time slice / scheduling information / struct task struct *parent; / this process’s parent / struct list head children; / this process’s children / struct files struct *files; / list of open files / struct mm struct *mm; / address space of this process*/ 30/09/2016 Systèmes d'Exploitation Avancés 16 Le Concept de Processus Process Control Block L'état d'un processus est représenté par long state dans cette structure. Dans le noyau Linux, tous les processus actifs sont représentés l'aide d'une liste doublement chaînée des task struct _ Le noyau maintien un pointeur current du processus en cours d'exécution sur le système. 30/09/2016 Systèmes d'Exploitation Avancés 17 Le Concept de Processus Process Control Block Supposons que le système voudrais modifier l'état du processus actuellement en cours d'exécution à la nouvelle valeur new state _ . Current pointant vers le processus en cours d'exécution, l'état est changé comme suit: current->state = new_state; 30/09/2016 Systèmes d'Exploitation Avancés 18 PROCESS SCHEDULING 30/09/2016 Systèmes d'Exploitation Avancés 19 Process Scheduling Dans un système multi-utilisateurs à temps partagé, plusieurs processus peuvent être présents en mémoire centrale en attente d'exécution. Si plusieurs processus sont prêts , le système d'exploitation doit gérer l'allocation du processeur aux différents processus à exécuter. C'est l'ordonnanceur qui s'acquitte de cette tâche. Un ordonnanceur fait face à deux problème : le choix du processus à exécuter, et le temps d'allocation du processeur au processus choisi. 30/09/2016 Systèmes d'Exploitation Avancés 20 Process Scheduling S.E préemptif Un système d'exploitation multitâche est préemptif lorsque celui-ci peut arrêter (réquisition) à tout moment n'importe quelle application pour passer la main à la suivante . Dans les systèmes d'exploitation préemptifs on peut lancer plusieurs applications à la fois et passer de l'une à l'autre , voire lancer une application pendant qu'une autre effectue un travail. le noyau garde toujours le contrôle se réserve le droit de fermer les applications qui monopolisent les ressources du système. Ainsi les blocages du système sont inexistants 30/09/2016 Systèmes d'Exploitation Avancés 21 Process Scheduling S.E coopératif Un système d'exploitation multitâche est coopératif Lorsqu'il permet à plusieurs applications de fonctionner et d'occuper des plages mémoire , laissant le soin à ces applications de gérer cette occupation , au risque de bloquer tout le système . 30/09/2016 Systèmes d'Exploitation Avancés 22 Process Scheduling Scheduling Queues Dès que les processus sont pris en charge par le S.E, ils sont placés dans une file d'attente ( job queue _ ), qui contient tous les processus dans le S.E. Les processus qui sont stockées dans la mémoire principale et sont prêtes et en attente d'exécution sont conservés dans une liste appelée ready queue _ Cette file d'attente est généralement implémenté sous la forme d'une liste chainée . La ready queue _ contient un en-tête ayants deux pointeurs: le permier vers le premier PCB, un deuxième vers le dernier PCB de la liste Chaque PCB comporte un pointeur qui pointe vers le prochain PCB de la ready queue _ 30/09/2016 Systèmes d'Exploitation Avancés 23 Process Scheduling Scheduling Queues Le système comprend également d’autres files d'attente. Quand un processus se voit allouer le CPU , il exécute pendant un certain temps et quitte, s’interromps ou attend l'occurrence d'un événement particulier, tel que l'achèvement d'une demande d‘E/S . Supposons que le processus effectue une demande d‘E/S à un device partagé, tel qu'un disque. Comme il existe de nombreux processus dans le système , le disque peut être occupé avec la demande d’E/S d'un autre processus. Le processus peut donc avoir à attendre le disque . La liste des processus en attente d’un device d’E/S est appelé device queue . Chaque device a sa propre device queue . 30/09/2016 Systèmes d'Exploitation Avancés 24 Process Scheduling Scheduling Queues 30/09/2016 Systèmes d'Exploitation Avancés 25 Process Scheduling Scheduling Queues Une représentation commune de l'ordonnancement des processus est un diagramme de files d'attente Chaque rectangle représente une file d'attente. deux types des files d'attente sont présentes: la ready queue _ et un ensemble de device queue _ . les cercles représentent les ressources qui servent les files d'attente, et les flèches indiquent les flux de processus dans le système. 30/09/2016 Systèmes d'Exploitation Avancés 26 Process Scheduling Scheduling Queues Un nouveau processus est d'abord mis dans la ready queue _ . Il attend dans cette file jusqu'à ce qu'il soit sélectionné pour l'exécution, ou est dispatché. Une fois que le processus se voit alloué le CPU, et est exécuté, un de ces événements pourrait se produire: Le processus pourrait émettre une demande d'E/S et ensuite être placé dans une file d'attente d'E/S . Le processus pourrait créer un nouveau sous-processus et attendre que la fin du sous-processus Le processus peut subir une interruption , enlevé de force du CPU, et mis en attente dans une device queue _ 30/09/2016 Systèmes d'Exploitation Avancés 27 Process Scheduling Schedulers Un processus migre entre différentes files d'attente d'ordonnancement tout au long de sa durée de vie . Le S.E doit sélectionner, à des fins de planification, les processus de ces files d'attente. Le processus de sélection est effectué par l’ordonnanceur (scheduler). 30/09/2016 Systèmes d'Exploitation Avancés 28 Process Scheduling Schedulers L'ordonnanceur à long terme fait la sélection de programmes à admettre dans le système pour leur exécution. Les programmes admis deviennent des processus à l'état prêt. L'admission dépend de la capacité du système (degré de multiprogrammation) et du niveau de performance requis. 30/09/2016 Systèmes d'Exploitation Avancés 29 Process Scheduling Schedulers Généralement le nombre de processus soumis est supérieur à la capacité de traitement immédiat du système. Ces processus sont en attente sur un dispositif de stockage de masse (généralement un disque), où ils sont conservés pour une exécution ultérieure. L'ordonnanceur à long terme , ou job scheduler , sélectionne les processus de ce pool et les charge en mémoire pour une exécution ultérieur. L'ordonnanceur à court terme , ou CPU scheduler , sélectionne parmi les processus qui sont prêts à être exécuter et alloue le CPU à l’un d’eux . 30/09/2016 Systèmes d'Exploitation Avancés 30 Process Scheduling Schedulers L'ordonnanceur à court terme a pour tâche la gestion des processus prêts. Il sélectionne en fonction d'une certaine politique le prochain processus à être exécuter. Il effectue aussi le changement de contexte des processus. Il peut implanter un ordonnancement préemptif, non préemptif, ou coopératif . L'ordonnanceur est activé par un événement : interruption du temporisateur, interruption d'un périphérique, appel système ou signal. 30/09/2016 Systèmes d'Exploitation Avancés 31 Process Scheduling Schedulers La principale distinction entre ces deux ordonnanceurs réside dans la fréquence d'exécution. L'ordonnanceur à court terme doit fréquemment sélectionner un nouveau processus pour la CPU. Un processus peut s'exécuter pour seulement quelques millisecondes avant une demande d‘E/S. Souvent, l'ordonnanceur à court terme s'exécute au moins une fois tous les 100 millisecondes. En raison de la courte période entre les exécutions, l’ordonnanceur à court terme doit être rapide. S'il faut 10 millisecondes pour décider d'exécuter un processus pour 100 millisecondes, 10 / (100 + 10) = 9 %de la CPU est utilisé (perdu) simplement pour planifier le travail . 30/09/2016 Systèmes d'Exploitation Avancés 32 Process Scheduling Schedulers L'ordonnanceur à long terme s’exécute beaucoup moins fréquemment - des minutes peuvent séparer la création de deux processus. L'ordonnanceur à long terme contrôle le degré de multiprogrammation (le nombre de processus en mémoire). Si le degré de multiprogrammation est stable alors le taux moyen de création de processus doit être égal à la moyenne des taux de départ du processus qui quittent le système. L'ordonnanceur à long terme est invoqué lorsqu’un processus quitte le système. 30/09/2016 Systèmes d'Exploitation Avancés 33 Process Scheduling Schedulers Les objectifs d'un ordonnanceur sont, entre autres : S'assurer que chaque processus en attente d'exécution reçoive sa part de temps processeur. Minimiser le temps de réponse. Utiliser le processeur à 100%. Utilisation équilibrée des ressources. Prendre en compte des priorités. Être prédictibles. 30/09/2016 Systèmes d'Exploitation Avancés 34 Process Scheduling Schedulers La plupart des processus peuvent être décrits comme des processus limités par les E/S ( I/O-bound process ) ou des processus limités par le CPU ( CPU-bound process) . Un processus est CPU-bound Génère rarement des E/S Passe plus de temps à faire des calculs sur le CPU sa progression est limitée par le CPU : si la CPU était plus rapide, il aurait terminé son exécution plus rapidement. Un processus et I/O-bound Génère un nombre important d’E/S (fichiers/accès disque/..) Sa progression est limitée par les E/S 30/09/2016 Systèmes d'Exploitation Avancés 35 Process Scheduling Schedulers Il est important que l' ordonnanceur à long terme fasse une sélection équilibrée entre les deux types de processus Si tous les processus sélectionnés sont des I/O-bound la ready-queue serait presque toujours vide L’ordonnanceur à court terme aura très peu à faire Si tous les processus sélectionnés sont des CPU-bound la file d'attente d‘E/S sera presque toujours vides, les devices (disques/…) seront sous utilisées Encore une fois le système sera déséquilibrée. Le système avec les meilleure performance devra avoir une combinaison de processus CPU-bound et I/O- bound. 30/09/2016 Systèmes d'Exploitation Avancés 36 Process Scheduling Schedulers Sur certains systèmes, l'ordonnanceur à long terme peut être absente ou minime. Par exemple, les systèmes à temps partagé comme UNIX et Microsoft Windows n'ont souvent pas d'ordonnanceur à long terme, Ils chargent simplement chaque nouveau processus dans la mémoire de l'ordonnanceur à court terme. La stabilité de ces systèmes dépend soit d’une limite physique (tel que le nombre de terminaux disponibles) ou de l’auto-ajustement de l'utilisateur humain (quittent leurs sessions en raison d’une baisse de performances du système). Ces systèmes introduisent un niveau intermédiaire d’ordonnanceur: les ordonnanceurs à moyen terme 30/09/2016 Systèmes d'Exploitation Avancés 37 Process Scheduling Schedulers L'idée principale derrière un ordonnanceur à moyen terme est que, parfois, il peut être avantageux d'éliminer les processus de la mémoire (et de la contention sur le CPU) et donc de réduire le degré de multiprogrammation . Plus tard, le processus peut être réintroduit dans la mémoire, et son l'exécution peut être poursuivie où il s'était arrêté . Ce schéma est appelé swapping . 30/09/2016 Systèmes d'Exploitation Avancés 38 Process Scheduling Schedulers 30/09/2016 Systèmes d'Exploitation Avancés 39 Process Scheduling Context Switch Lorsqu'une interruption se produit, le système doit sauvegarder le contexte actuel du processus en cours d'exécution sur le processeur de telle sorte que il peut restaurer ce contexte lorsque son traitement est effectué, Le contexte est représenté par le PCB du processus De manière générique, le S.E procède à une sauvegarde d’état (state save) du CPU (que ce soit en user mode ou en kernel mode) puis effectue une restauration de l'état (state restore) pour reprendre une exécution. 30/09/2016 Systèmes d'Exploitation Avancés 40 Process Scheduling Context Switch Switcher la CPU d’un processus à un autre nécessite l'exécution d'une sauvegarde d'état du processus en cours et une restauration état d'un processus suivant . → Cette tâche est connue sous le nom d'un commutation de contexte. 30/09/2016 Systèmes d'Exploitation Avancés 41 Process Scheduling Context Switch Lorsqu’une commutation de contexte se produit le noyau enregistre le contexte de l'ancien processus dans son PCB et charge le contexte sauvegardé du nouveau processus pour s'exécuter. Le temps de commutation de contexte est considérer comme un overhead Le S.E n’exécute aucune tâche durant ce temps. Sa vitesse varie selon les machine, il dépend de la vitesse de la mémoire, le nombre de registres qui doivent être copié, et l'existence d'instructions particulières (comme une seule instruction pour charger ou stocker tous les registres). Les vitesses typiques sont quelques millisecondes. 30/09/2016 Systèmes d'Exploitation Avancés 42 LES OPERATIONS SUR LES PROCESSUS 30/09/2016 Systèmes d'Exploitation Avancés 43 Les Operations sur les Processus Les processus dans la plupart des systèmes peuvent s'exécuter en même temps, et ils peuvent être créés et supprimés de manière dynamique. Ainsi, ces systèmes doivent fournir une mécanisme de création de processus et de terminaison 30/09/2016 Systèmes d'Exploitation Avancés 44 Création de processus Un processus ( processus parent ) peut créer plusieurs nouveaux processus ( processus fils ), via un appel système au cours de l'exécution. Chacun de ces de nouveaux procédés peuvent à leur tour créer d'autres processus, formant ainsi un arbre de processus. La plupart des systèmes d’exploitation identifie un processus via un PID, qui est typiquement un nombre integer. 30/09/2016 Systèmes d'Exploitation Avancés 45 Création de processus 30/09/2016 Systèmes d'Exploitation Avancés 46 Naissance Création de processus arbre des processus dans Solaris Sous Solaris, le processus au sommet de l'arbre est le processus sched, avec un pid de 0. Le processus sched crée plusieurs enfants , y compris les processus pageout et fsflush . Ces processus sont responsables de la gestion de la mémoire et des systèmes de fichiers. Le processus sched crée également le processus init, qui sert que le processus parent racine pour tous les processus utilisateur. Init a deux enfants: netd et dtlogin. inetd est chargé des services réseaux tels que telnet et ftp dtlogin est le processus qui fournit à l’utilisateur un écran de connexion. Quand un utilisateur se connecte, dtlogin crée une session X-Windows ( Xsession ), qui à son tour crée le processus sdt_shel. 30/09/2016 Systèmes d'Exploitation Avancés 48 Création de processus En général, un processus a besoin de certaines ressources (temps CPU, la mémoire, les fichiers, périphériques E/S) pour accomplir sa tâche. Quand un processus crée un sous-processus , le sous processus peut être en mesure d'obtenir ses ressources directement à partir de l'exploitation système , ou bien il peut être limitée à un sous-ensemble des ressources du processus père . Le père peut avoir à partitionner ses ressources entre ses enfants, ou il peut être en mesure de partager certaines ressources (comme la mémoire ou les fichiers) entre plusieurs de ses enfants. 30/09/2016 Systèmes d'Exploitation Avancés 49 Création de processus Quand un processus crée un nouveau processus, il existe deux possibilités d'exécution: Le parent continue d'exécuter en même temps que ses enfants. Le parent attend jusqu'à ce que tout ou partie de ses enfants ont pris fin. Il y a aussi deux possibilités pour la gestion de l'espace d'adressage du nouveau processus: Le processus fils est une copie du processus parent (il a le même programme et les données en tant que parent). Le processus fils a un nouveau programme chargé . 30/09/2016 Systèmes d'Exploitation Avancés 50 Création de processus Pour illustrer ces différences, nous allons d'abord examiner le système d'exploitation UNIX. Un nouveau processus est créé par fork() du système appelant. Le nouveau processus comprend une copie de l'espace d'adressage de l'original processus . Ce mécanisme permet au processus parent de communiquer facilement avec son processus enfant. Les deux processus (le parent et l'enfant) poursuivre l'exécution à l'instruction après le fork() , avec une différence: le code retour du fork() est égal à zéro pour le nouveau (enfant) processus, alors que le PID (non nulle) de l'enfant est retourné au processus père. 30/09/2016 Systèmes d'Exploitation Avancés 51 Création de processus En règle générale, l'appel système exec() est utilisée après un appel système fork() par l'un des deux processus afin de remplacer l'espace mémoire du processus avec une nouveau programme . L'appel système exec() charge un fichier binaire en mémoire (destruction de l'image mémoire du programme contenant l’appel système exec()) et commence son exécution. De cette manière, les deux processus sont en mesure de communiquer puis se séparent. Le parent peut alors créer plus d'enfants, ou, si il n'a rien d'autre à faire alors que l'enfant s'exécute , il peut émettre un appel système wait() afin de mettre hors de la ready_queue jusqu'à la terminaison du processus fils. 30/09/2016 Systèmes d'Exploitation Avancés 52 Makefile CC=gcc CFLAGS=-W -Wall -ansi –pedantic EXEC=exemple1 all: exemple1 exemple1.o: exemple1.c $(CC) -o exemple1.o -c exemple1.c $(CFLAGS) clean: rm -rf *.o mrproper: clean rm -rf $(EXEC) 30/09/2016 Systèmes d'Exploitation Avancés 53 Création de processus #include #include #include #include int main() { pid_t pid; /* fork a child process */ pid = fork(); if (pid < 0) { /* error occurred */ fprintf(stderr, "Fork Failed"); return 1; } else if (pid == 0) { /* child process */ printf("Child Process says Hello !\n"); execlp("/bin/ls","ls",NULL); } else { /* parent process / / parent will wait for the child to complete */ printf("Parent Process says Hello !\n"); wait(NULL); printf("Child Complete"); } return 0; } 30/09/2016 Systèmes d'Exploitation Avancés 54 Création de processus 30/09/2016 Systèmes d'Exploitation Avancés 55 Identification par le PID Le premier processus du système, init, est créé directement par le noyau au démarrage. La seule manière, ensuite, de créer un nouveau processus est d'appeler l'appel-système fork( ), qui va dupliquer le processus appelant. Au retour de cet appel-système, deux processus identiques continueront d'exécuter le code à la suite de fork( ). La différence essentielle entre ces deux processus est un numéro d'identification. On distingue ainsi le processus original, qu'on nomme traditionnellement le processus père, et la nouvelle copie. Le processus fils. L'appel-système fork( ) est déclaré dans , ainsi : pid_t fork(void); 30/09/2016 Systèmes d'Exploitation Avancés 56 Identification par le PID Les deux processus pouvant être distingués par leur numéro d'identification PID (Process IDentifier), il est possible d'exécuter deux codes différents au retour de l'appel- système fork( ). Par exemple. le processus fils peut demander à être remplacé par le code d'un autre programme exécutable se trouvant sur le disque. C'est exactement ce que fait un shell habituellement. Pour connaître son propre identifiant PID, on utilise l'appel- système getpid( ), qui ne prend pas d'argument et renvoie une valeur de type pid_t. Il s'agit. bien entendu, du PID du processus appelant. Cet appel-système déclaré dans , est l'un des rares qui n'échouent jamais : pid_t getpid (void); 30/09/2016 Systèmes d'Exploitation Avancés 57 Identification par le PID Ce numéro de PID est celui que nous avons vu affiché en première colonne de la commande ps. La distinction entre processus père et fils peut se faire directement au retour de l'appel fork( ). Celui-ci, en effet. renvoie une valeur de type pid_t, qui vaut zéro si on se trouve dans le processus fils, est négative en cas d'erreur, et correspond au PID du fils si on se trouve dans le processus père. 30/09/2016 Systèmes d'Exploitation Avancés 58 Identification par le PID Voici en effet un point important : dans la plupart des applications courantes, la création d'un processus fils a pour but de faire dialoguer deux parties indépendantes du programme (à l'aide de signaux, de tubes, de mémoire partagée...). Le processus fils peut aisément accéder au PID de son père (noté PPID pour Parent PID) grâce à l'appel-système getppid(), déclaré dans : pid_t getppid (void); Cette routine se comporte comme getpid( ), mais renvoie le PID du père du processus appelant. Par contre, le processus père ne peut connaître le numéro du nouveau processus créé qu'au moment du retour du fork( ). 30/09/2016 Systèmes d'Exploitation Avancés 59 Identification par le PID On peut examiner la hiérarchie des processus en cours sur le système avec le champ PPID de la comande ps axj: 30/09/2016 Systèmes d'Exploitation Avancés 60 Identification par le PID Lorsqu'un processus est créé par fork( ), il dispose d'une copie des données de son père, mais également de l'environnement de celui- ci et d'un certain nombre d'autres éléments (table des descripteurs de fichiers, etc.). On parle alors d'héritage du père. Notons que, sous Linux, l'appel-système fork() est très économe car il utilise une méthode de « copie sur écriture ». - Cela signifie que toutes les données qui doivent être dupliquées pour chaque processus (descripteurs de fichier, mémoire allouée...) ne seront pas immédiatement recopiées. Tant qu'aucun des deux processus n'a modifié des informations dans ces pages mémoire, il n'y en a qu'un seul exemplaire sur le système. Par contre, dès que l'un des processus réalise une écriture dans la zone concernée, le noyau assure la véritable duplication des données. Une création de processus par fork() n'a donc qu'un coût très faible en termes de ressources système. 30/09/2016 Systèmes d'Exploitation Avancés 61 Identification par le PID En cas d'erreur, fork() renvoie la valeur -1, et la variable globale errno contient le code d'erreur, défini dans , ou plus exactement dans , qui est inclus par le précédent fichier d'en-tête. Ce code d'erreur peut être soit ENOMEM , qui indique que le noyau n'a plus assez de mémoire disponible pour créer un nouveau processus, soit EAGAIN , qui signale que le système n'a plus de place libre dans sa table des processus mais qu'il y en aura probablement sous peu. Un processus est donc autorisé à réitérer sa demande de duplication lorsqu'il a obtenu un code d'erreur EAGAIN . 30/09/2016 Systèmes d'Exploitation Avancés 62 Identification par le PID #include #include #include #include #include int main (void) { pid t pid fils; do { pid fils = fork ( ) ; }while ((pid fils == -1) && (errno == EAGAIN)); if (pid_fils == -1) { fprintf(stderr,"fork( ) impossible, errno= %d\n", errno); return (1); } if (pid_fils == 0) { fprintf (stdout, "Fils : PID=%d, PPID=%d\n",getpid( ),getppid( )) return (0); } else { fprintf (stdout, “Pére :PID=%d,PPID=%d,PID FILS= %d\n",getpid( ) ,getppid( ),pid_fils); wait(NULL); return(0); } return 0; } 30/09/2016 Systèmes d'Exploitation Avancés 63 Identification par le PID Dans notre exemple, l'appel-système fork( ) boucle si le noyau n'a plus assez de place dans sa table interne pour créer un nouveau processus. Dans ce cas, le système est déjà probablement dans une situation assez critique, et il n'est pas utile de gâcher des ressources CPU en effectuant une boucle hystérique sur fork( ). Il serait préférable d'introduire un délai d'attente dans notre code pour ne pas réitérer notre demande immédiatement, et attendre ainsi pendant quelques secondes que le système revienne dans un état plus calme 30/09/2016 Systèmes d'Exploitation Avancés 64 Identification par le PID On remarquera que nous avons introduit un appel-système wait(NULL) à la fin du code du père. Nous en reparlerons ultérieurement, mais on peut d'ores et déjà noter que cela permet d'attendre la fin de l'exécution du fils. Si nous n'avions pas employé cet appel système, le processus père aurait pu se terminer avant son fils, redo...