Architecture des ordinateurs TP5

by Joseph Razik, on 2023-04-17

5   Gestion mémoire et ordonnacement des processus sous Unix

5.1   Objectif

L'objectif de ce TP est d'étudier un ensemble de commandes shell sous UNIX/Linux permettant de créer, gérer et détruire les processus d'une machine, étudier le fonctionnement de la mémoire et d'un ordonnanceur à l'aide de logiciels de simulation.

5.2   Préambule

La variable d'environnement PATH

Les commandes que vous entrez dans le terminal doivent être connues du système pour être exécutées. Pour cela, soit vous indiquez précisément le chemin permettant d'atteindre cet exécutable, soit une variable d'environnement défini les chemins des répertoires où chercher cet exécutable. Cette variable se nomme PATH. Vous pouvez voir son contenu avec la commande suivante:

>$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Une commande ne se trouvant pas dans ces répertoires ne pourra être exécutée qu'en précisant son chemin d'accès. Par exemple, pour exécuter le programme demoNice qui se trouve dans /home/partage/I22/, si on ne précise pas le chemin, voici ce que l'on obtient:

>$ demoNice
demoNice : commande introuvable

Pour l'exécuter, vous devez donner le chemin (absolu ou relatif) pour y accéder:

>$ /home/partage/I22/demoNice

Si vous êtes dans le répertoire contenant le programme, la spécification du chemin se fait ainsi:

>$ ./demoNice

La commande grep

Le répertoire /proc/ contient des informations sur le système d'exploitation en cours d'exécution, les processus, etc. Dans ce répertoire, le fichier cpuinfo contient des informations sur le type de CPU sur lequel fonctionne le système.

  1. A l'aide de la commande grep et de ses options déterminez le modèle de processeur, ainsi que le nombre de processeur dans le CPU (c'est à la commande grep de compter). Vous pourrez dans un premier temps utiliser la commande less ou more afin de savoir quel motif chercher.

La commande du

La commande du permet d'afficher une estimation de l'espace disque utilisé par un ou plusieurs fichiers ou répertoires.

  1. Créez le fichier vide /tmp/fichier_vide à l'aide de la commande touch.
  2. Quelle est la taille de ce fichier telle que donnée par la commande ls ?
  3. Quelle est la taille de ce fichier telle que donnée par la commande du ?
  4. Écrivez le texte « quelques mots » dans le fichier précédent. Quelles sont maintenant les tailles données par les commandes ls et du ? Pourquoi ?

5.3   Création de processus

Dans un terminal, il est possible de créer un nouveau processus indépendant dit « enfant » à partir d'un processus « parent ». Pour cela il suffit d'ajouter le caractère spécial "&" après le nom d'une commande (on dit aussi lancement en mode détaché). Avant de revenir au prompt (invite de commande shell), apparaît un numéro de tâche et le numéro du processus lancé (Pid). Ce numéro identifie de manière unique le processus lancé.

Expérimentez la création de nouveaux processus avec et sans cette commande en lançant plusieurs processus différents ou identiques à partir d'un terminal (un éditeur (gedit) ou une calculatrice (gnome-calculator) ou une horloge (xclock)).

Points importants dans l'utilisation de "&"

  • Le nouveau processus en tâche de fond ne doit pas attendre de saisie au clavier. Le shell doit avoir le monopole de l'accès au clavier ;
  • Le processus en tâche de fond ne doit pas retourner ses résultats sur le terminal. Sinon les sorties de ce processus risquent d'entrer en conflit avec celles du shell ou d'une autre commande (mélange des caractères à l'écran !).

5.4   Liste des processus du système

Les caractéristiques importantes d'un processus UNIX sont:

  • Son identification (un nombre entier) ou PID,
  • L'identification du processus parent qui l'a créé (PPID),
  • Son propriétaire,
  • Son groupe propriétaire,
  • Son état,
  • Le temps cumulé d'exécution,
  • Éventuellement son terminal d'attachement.

La commande ps

Cette commande permet d'afficher la liste des processus avec la possibilité de filtrer les caractéristiques à afficher.

  1. Étudiez les différentes options disponibles, en particulier -l, -e, -f et -u.
  2. Quelle est l'option permettant d'afficher tous les processus du système ?
  3. Quelle est l'option permettant d'afficher uniquement tous les processus dont vous êtes le propriétaire ?
  4. Repérez les états des processus.
  5. Repérez la priorité du processus de votre terminal (attention, la valeur affichée est diminuée de 40 par rapport à sa valeur réelle).
  6. Repérez la valeur "nice" du processus de votre terminal.
  7. Pourquoi dans la liste de vos processus apparaît-il la commande ps ?
  8. Comment peut-on repérer des processus enfants d'autres processus ?
  9. Quel est le processus parent de tous les autres ?
  10. Créez de nouveaux processus avec le caractère spécial "&" à partir du terminal et vérifiez la relation parent - enfant.

La commande pstree

Cette commande permet de visualiser sous forme graphique les relations parent-enfant dans la liste des processus du système.

NB: Elle n'est pas installée par défaut dans tous les systèmes.

  1. Quelles sont les options pour afficher le PID des processus et pour afficher uniquement vos processus ?

5.5   Manipulation des processus entre l'avant plan (premier plan) et l'arrière plan

Les commandes "bg", "fg", "jobs" et Ctrl-Z permettent de manipuler la notion d'avant plan et d'arrière plan pour un processus. Elles sont intimement liées au SHELL.

Un processus en avant plan s'exécute en ayant la main sur le terminal qui l'a lancé (le bloque). Un processus en arrière plan s'exécute de façon détachée par rapport au terminal qui l'a lancé (pas de blocage).

La commande "jobs" permet d'afficher les processus activés ou suspendus (STOPPED) et leur numéro. Attention, cette commande n'affiche que les processus lancés à partir du terminal où elle est exécutée.

Pour suspendre l'exécution d'un processus en avant plan et revenir au terminal, il existe la séquence de touches Ctrl-z. Ensuite, à partir de ce même terminal, il est possible :

  • soit de remettre en avant plan une tâche : commande "fg %n° de job" ou "fg n° de job" ;
  • soit de lancer en mode détaché une tâche : commande "bg %n° de job"
  1. À partir d'un terminal, ouvrez une fenêtre horloge avec la commande "xclock -update 2". Que constatez-vous ? Pouvez-vous lancer d'autres commandes dans le terminal ?
  2. Suspendez-la avec la séquence de touches Ctrl-z. Que constatez-vous ? Pouvez-vous lancer d'autres commandes dans le terminal ?
  3. En utilisant la commande "jobs", déterminez quel est l'état de ce processus.
  4. Relancez-le en arrière-plan avec la commande "bg". Que se passe-t-il ? Pouvez-vous lancer d'autres commandes dans le terminal ?
  5. Vérifiez avec la commande "jobs"

5.6   Envoi de messages aux processus

La commande "kill" permet d'envoyer à un ou plusieurs processus, identifiés par leur PID, un signal prédéfini dans le système (par ex. SIGINT, …). L’utilisation de la commande "kill" est limitée aux processus appartenant à l’utilisateur sauf pour l'utilisateur root qui peut envoyer des signaux à tous les processus.

  • Expérimentez la commande "kill -l". Qu’affiche-t-elle ? Pour comprendre cet affichage, ouvrez avec gedit le fichier "/usr/include/x86_64-linux-gnu/bits/signum-generic.h".
  • Quel est le signal pour suspendre l'exécution d'un processus ? Faites un test avec ce signal sur un nouveau processus que vous avez créé.
  • Quel est le signal (ou les signaux) pour arrêter définitivement un processus ?

On peut, à la place du PID, utiliser le numéro de job affiché avec la commande jobs. Créez un processus détaché (xclock par exemple) et envoyez-lui un signal SIGKILL avec son numéro de job (%n°).

D'autres commandes basées sur kill permettent une utilisation parfois plus adaptée de l'envoie de signal, par exemple killall, pkill ou xkill. Lisez le manuel afin de comprendre les nuances entre ces commandes et expérimentez-les.

5.7   Mesure du temps d'exécution des processus

La commande "time" permet de mesurer le temps d'exécution d'un processus.

  1. La commande "time" retourne plusieurs valeurs, à quoi correspondent-elles ?
  2. Exécutez la commande "time gedit&". Quand la commande "time" rend-elle son résulat ?
  3. Pour la commande "time ls -lR /usr/lib > /dev/null", calculez le ratio temps CPU / temps réel.

5.8   La commande top

La commande top permet d'afficher en dynamique certaines valeurs du système (processus, temps, priorité, utilisation mémoire). Vous pouvez quitter cette commande avec la touche 'q'. Par défaut la mise à jour des informations a lieu toutes les 3 secondes. Vous pouvez régler un grand nombre de paramètres avant le lancement de l'exécution (surveiller les processus d'un utilisateur particulier par exemple) ou les changer en cours d'exécution (touche 'h'). Lire les premières pages du man pour découvrir la commande.

  1. Lancez la commande top et visualisez les différents paramètres (mémoire physique, mémoire swap, PID, Priorité, %CPU et MEM).
  2. Notez le nombre de processus running, sleeping, stopped, zombie.
  3. Trouvez la touche permettant, en mode interactif, d'afficher le réglage des données à visualiser et affichez les données DATA et CODE.
  4. Trouvez la touche permettant, en mode interactif, de sélectionner uniquement vos processus.
  5. Lancez dans un autre terminal le programme demoNice qui se trouve dans le répertoire /home/partage/I22/. Faire start et observer le comportement des paramètres du processus avec la commande top. Quelle est la charge CPU et mémoire de ce processus ?
  6. Arrêtez le programme demoNice et relancez en regardant précisément la valeur de la colonne PR de ce processus dans les informations de top. Que constatez-vous ?

NB: il existe également la commande htop qui est assez similaire et parfois plus commode mais qui n'est pas forcément installée par défaut dans les distributions.

5.9   Test de la commande nice

La commande nice permet de modifier la priorité d'un processus. L'utilisateur peut seulement diminuer la priorité d'un processus en ajoutant une valeur (de 1 à 19) à la valeur actuelle de la priorité du processus (par défaut le facteur nice est à 0). L'administrateur peut augmenter ou diminuer la priorité d'un processus (de -20 à 19).

La syntaxe est : nice -valeur 'programme à exécuter'.

Cette commande est aussi accessible à partir de l'API C. Afin de visualiser l'effet du changement de priorités des processus nous allons exécuter deux processus identiques qui effectuent un calcul long et observer la variation du temps d’exécution lorsqu’on fait varier la priorité du processus avec des appels C à la fonction nice().

Attention

Pour cette exercice sur la commande nice, afin de mieux voir l'effet escompté tous les processus s'exécuteront sur le même processeur (coeur). La plupart des processeurs sont multi-coeurs, ce qui est vu par le système comme une architecture multiprocesseurs.

Si le nombre de processeurs vu par le système est supérieur à 1, le programme utilisé forcera son exécution (les processus demoNice) à s'exécuter sur le même coeur. Pour cela, il modifie ce que l'on appelle le cpu affinity.

Questions

  1. Lancez deux instances du programme demoNice en tapant /home/partage/I22/demoNice & et observez la variation du temps d’exécution selon le facteur nice lors d'un calcul en parallèle. Par exemple, que se passe-t-il si un programme (A) a comme facteur 19, par rapport à un programme (B) qui a un facteur 0 ? image6

  2. Que se passe-t-il si le programme (B) se bloque (en pause) pendant l'exécution parallèle ?

  3. Fermez les deux programmes précédemment lancés et exécutez 2 nouvelles instances avec comme facteur nice 0 et 5. Quel se passe-t-il ? Pourquoi est ce différent du cas précédent ?

  4. Fermez les deux programmes précédemment lancés et exécutez 3 nouvelles instances avec comme facteur nice 0, 10 et 19. Quel est le résultat ? image7

  5. En utilisant trois terminaux, un pour chaque commande demoNice, lancez de manière synchronisée trois demoNice avec les mêmes caractèristiques de nice que pour la question précédente et observez les temps d'exécution de chaque processus sachant que vous stopperez les processus dés que le premier (nice = 0) aura fini son calcul en cliquant sur le X de la fenêtre. Que constate-t-on ?

    NB: les valeurs seront partiellement différentes pour le temps d'exécution. Ceci est dû au lancement et l'arrêt séquentiel des processus, mais l'erreur introduite est négligeable pour la mesure voulue.

  6. Lancez de nouveau deux instances de demoNice en tapant /home/partage/I22/demoNice & dans un terminal. Dans un autre terminal lancez la commande htop. Filtrez l’affichage de htop pour afficher ces deux processus. Changez les valeurs de nice dans les deux fenêtres (par ex 5 et 12). Vérifiez la prise en compte au niveau système de vos modifications dans l’interface de htop.

  7. Ré-affichez la liste des différents processus cette fois à l'aide de ps et la valeur nice associée aux processus demoNice (attention, ils ne portent peut-être pas ce nom). Quelle est la valeur nice de la plupart des processus actifs ?

5.10   Différents algorithmes d'ordonnancement

L'analyse de certains algorithmes est illustrée avec le programme Simor. Simor est un simulateur graphique d'ordonnancement qu'il faut lancer à partir de de la commande

java -jar /home/partage/I22/Simor.jar

Présentation du simulateur Simor

Lancer le simulateur avec la commande précédente et découvrez l'interface utilisateur.

image0

La zone centrale de la partie haute de Simor permet de définir le nombre de processus dans la simulation ainsi que le quantum pour le système Tourniquet (Round Robin).

image1

La zone basse dans la partie gauche permet de définir les paramètres des différents processus créés : leur temps d'exécution nécessaire et leur date d'arrivée.

image2

La zone droite du simulateur présente le bouton principal permettant de lancer la simulation pour toutes les politiques d'ordonnancement définies dans Simor.

image3

L'écran de Simor présente une barre d'onglets et 3 zones.

Les résultats de la simulation s'affichent dans chacun des onglets de la barre d'onglets dans la partie supérieure du simulateur.

Divers graphiques de simulation et différentes valeurs sont proposées pour chaque politique.

image4

Algorithme FCFS (FIFO) : First Come-First Served

Créez deux processus avec une durée d'exécution de 15 s et un temps d'arrivée de 2 s.

  1. Lancez la simulation et visualisez le résultat dans l'onglet FCFS. Que se passe-t-il ? Dans quel ordre sont élus les processus ?
  2. Recommencez l'opération en créant un troisième processus avec comme durée d'exécution 30 s et un temps d'arrivée de 0s.
  3. Que se passe-t-il ? Que provoque le processus 3 d'une durée plus longue ?
  4. Calculer le tma pour 3 processus P1, P2, P3 d'une durée respective de 50 s, 25 s et 8 s et un temps d'arrivée nul.

Algorithme SJF : Shortest-Job-First (PCTE)

SJF : la prochaine tâche dont le cycle d'UC total est le plus court (mode non préemptif).

Créez 3 processus avec les paramètres suivants:

  • P1 (durée= 5 s, arrivée= 0 s),
  • P2 (durée= 7 s, arrivée= 0 s),
  • P3 (durée= 3 s, arrivée= 0 s).
  1. Lancez la simulation et analysez les résultats de l'onglet SJF.
  2. Créez un quatrième processus avec les paramètres suivants: P4 (d=2 s, a=4 s). Observez les modifications d'exécution dans ce contexte.
  3. Expérimentez encore avec un cinquième processus P5 (d=2 s, a=3 s).
  4. Calculez le tma pour 3 processus P1, P2, P3 d'une durée respective de 50 s, 25 s et 8 s et aucun retard au départ.

Algorithme RR : tourniquet - Round-Robin

Cet algorithme a été conçu spécialement pour les systèmes en temps partagé. Il est similaire au FCFS mais avec préemption après une tranche de temps (quantum) d’exécution (généralement entre 10 et 100 ms).

Créez 4 processus avec les paramètres suivants:

  • P1 (d= 50 s, r= 0 s),
  • P2 (d= 70 s, r= 0 s),
  • P3 (d= 30 s, r= 0 s),
  • P4 (d= 80 s, r= 0 s),
  • un quantum de 10 s.
  1. Lancez la simulation et observez l'exécution des processus pour la politique RR. Que se passe-t-il ?
  2. Quel est le temps d'attente maximal et moyen ?
  3. Recommencez le test en réglant le quantum à 1 s. Que constatez-vous ?
  4. Recommencez le test en réglant le quantum à 90 s. Que constatez-vous ? À quel algorithme ressemble maintenant l'allocation du processeur ?
  5. Calculez le tma pour 3 processus P1, P2, P3 d'une durée respective de 500 s, 250 s et 80 s avec un quantum de 1 s et aucun retard au départ.

5.11   Algorithme de scheduling du noyau UNIX

Ce type de scheduling de l'UC est conçu pour que les processus interactifs soient avantagés. Un algorithme avec des priorités donne aux processus de courtes tranches de temps d'UC. Cet algorithme se réduit à un scheduling de type tourniquet.

Une priorité de scheduling est associée à chaque processus; un nombre plus grand indique une priorité plus petite. Les processus qui effectuent des entrées sorties ou d'autres tâches importantes possèdent des priorités importantes et on ne peut les préempter (exécution en mode noyau). Les processus utilisateurs possèdent des priorités faibles, inférieures au processus noyau. Il est en outre possible de moduler les priorités des processus utilisateurs avec la commande nice().

Plus un processus accumule du temps processeur, plus basse devient sa priorité (plus grande valeur) et vice-versa. Il existe donc un feedback négatif dans le scheduling de l'UC, et il est difficile pour un seul processus de prendre tout le temps processeur. Le vieillissement des processus est utilisé pour éviter la famine.

NB : À noter que le scheduling de LINUX prévoit dans son extension POSIX 1003.4, la notion de processus temps réel et dispose de 2 politiques supplémentaires SCHED_FIFO et SCHED_RR avec dans ce cas des priorités fixes. Les processus s’exécutant suivant ces politiques s’exécutent de façon prioritaire par rapport aux processus classiques à priorité dynamique. Ils sont cependant préemptables par le système et ne peuvent bloquer le processeur. Ces modes ont été rajoutés pour apporter au système un certain contrôle de la réactivité face à des événements extérieurs à la machine, le but étant d’essayer d’intégrer du déterminisme dans le traitement des processus.

Pour information, la valeur de priorité la plus forte pour les processus utilisateurs est définie à 120 et la valeur nice par défaut est 0.

5.12   Système de fichiers

Les i-nodes

Sous Unix/Linux, pour la gestion du système de fichiers, chaque fichier est identifié par un numéro unique: l'i-node. À cet identifiant est associé plusieurs informations concernant le fichier qui permettent au système d'exploitation de bien gérer les actions liées au système de fichiers. Parmi ces informations on retrouve le type, la taille et le contenu du fichier.

  1. Quelles options des commandes ls et stat permettent de voir ces informations (taille, i-node, droits etc) ?
  2. Comment afficher à l'aide de la commande ls la liste des fichiers triée du plus ancien au plus récent, en affichant cette date, les droits, la taille etc ?

Liens physiques

Sous Unix/Linux il existe la possibilité de créer des liens entre fichiers afin de permettre par exemple de créer plusieurs noms faisant référence au même i-node, et donc au même fichier. Pour cela il faut utiliser la commande ln. Il existe deux types de lien: les liens physiques (hard link) et les liens symboliques (soft link).

  • Créez deux fichiers: le fichier one contenant la valeur 1 et le fichier two contenant la valeur 2.
  • Créez ensuite à l'aide de la commande ln le fichier un et le fichier deux en tant que lien physique vers respectivement one et two.
  1. Comment apparaissent ces deux fichiers avec la commande "ls -l" ?
  2. Modifiez le fichier one pour y mettre la valeur 3. Que contiennent les fichiers one, two, un et deux ? Que remarquez-vous ?
  3. Quels sont les i-nodes de ces 4 fichiers ?
  4. Que fait donc la commande ln en création de lien physique ?
  5. Comparez l'i-node du dossier courant (à partir de son parent) et l'i-node du dossier ”.” situé dans le dossier courant ? À quel répertoire correspond l'i-node de ”..” ? Expliquez.

Liens symboliques

Les fichiers de lien symbolique contiennent une référence à un autre fichier et leur contenu peut être vu comme “simplement” un chemin (absolu ou relatif) vers l'autre fichier. Comme pour les liens physiques, toutes les commandes effectuées sur un fichier lien sont en fait effectuées sur le fichier référencé. Mais contrairement aux liens physiques, il y a bien deux fichiers différents qui sont créés car ils ont deux i-nodes différents. On dit simplement que le fichier lien pointe vers un autre fichier.

Pour créer un lien symbolique il suffit d’ajouter l’option -s à la commande ln. En effet, par défaut la commande ln crée un lien physique. La commande "ls -l" permet d’identifier les liens non seulement par leur type mais indique aussi le fichier référencé. De plus il est possible de créer des liens vers des répertoires car tout répertoire est en fait un fichier.

  • Créez un répertoire FR et un répertoire EN.
  • Notez les i-nodes des fichiers un, deux, one et two
  • Placez dans FR les fichiers un et deux précédents et dans le répertoire EN les fichiers one et two précédents.
  1. Leurs i-nodes ont-ils changé ?
  • Créez dans le répertoire FR le fichier trois contenant la valeur 3.
  • Créez dans le répertoire EN le fichier three en tant que lien symbolique vers le fichier trois du répertoire FR par un adressage relatif.
  1. Quels sont les i-nodes de ces deux fichiers ? Qu'affiche la commande ls -l dans le répertoire EN ?
  2. Créez au même niveau que les répertoires EN et FR le nouveau répertoire US comme étant un lien symbolique de EN. Quel est l'i-node de US ? Le répertoire US contient-il des fichiers et si oui à quoi correspondent leur i-nodes ?
  3. Modifiez la valeur du contenu de US/three à la valeur 3.0 . Quel est le contenu des fichiers FR/trois et EN/three ?
  4. Déplacez le fichier US/three dans le répertoire /tmp/. Quel est son i-node et quel est son contenu ?
  5. Après avoir remis le fichier /tmp/three à son emplacement original (répertoire EN), ouvrez dans un éditeur le fichier US/three et laissez le ouvert (par exemple vim, emacs). En parallèle, dans un terminal, après avoir fait un ls, supprimez le fichier FR/trois et faire de nouveau ls.
  6. Modifiez dans l'éditeur la valeur par 3 et sauvez le fichier (en gardant l'éditeur ouvert). Refaire ls. Que remarquez-vous ?
  7. Comment peut-on connaître le nombre de noms/liens que possède un fichier ?