0% ont trouvé ce document utile (0 vote)
204 vues33 pages

Introduction aux systèmes d'exploitation

Ce document traite de l'introduction aux systèmes d'exploitation. Il définit ce qu'est un système d'exploitation et présente son historique et sa structure. Il aborde également la gestion des processus, des threads, l'ordonnancement des processus, la communication et la synchronisation interprocessus et la gestion de la mémoire.

Transféré par

loic ngounou
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
204 vues33 pages

Introduction aux systèmes d'exploitation

Ce document traite de l'introduction aux systèmes d'exploitation. Il définit ce qu'est un système d'exploitation et présente son historique et sa structure. Il aborde également la gestion des processus, des threads, l'ordonnancement des processus, la communication et la synchronisation interprocessus et la gestion de la mémoire.

Transféré par

loic ngounou
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Université de Yaoundé I

Faculté des Sciences

Département d’Informatique

ICT4D

ICT204 Introduction au système d’exploitation

Polycarpe Siekambe

Année académique 2020-2021


Table des matières

1 Definition et historique 3
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Qu’est-ce q’un système d’exploitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Historique des systèmes d’exploitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.3 Structure d’un système d’exploitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.4 Appels système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 GESTION DES PROCESSUS ET DES THREADS 8


2.1 Définition et caractéristiques d’un processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Etats d’un processus et changement de contexte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Création et manipulation de base d’un processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.1 Création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.2 Appels système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.3 Terminaison de processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4 Les threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4.1 Définition et caractérisques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4.2 Avantages des threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4.3 Appels system de gestion des threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 ORDONNANCEMENT DES PROCESSUS 18


3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 Définitions de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.1 Types d’ordonnanceurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.3 Politiques d’ordonnancement non préemptif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4 Politiques d’ordonnancement préemptif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4.1 Ordonnancement du plus petit temps de séjour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4.2 Ordonnancement circulaire (Round robin) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4.3 Ordonnancement avec priorité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4 COMMUNICATION SYNCHRONISATION INTERPROCESSUS 23


4.1 Introdution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2 Les données communes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

5 GESTION DE LA MEMOIRE 25
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.2 Monoprogrammation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.3 Multiprogrammation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.3.1 Multiprogrammation à partitions fixe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.3.2 Fragmentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.3.3 Swaping (Va-et-vient) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.3.4 Gestion de la mémoire par table de bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.3.5 Gestion de la mémoire par liste chaînée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.3.6 Algorithmes d’allocation de la mémoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

1
2/32 TABLE DES MATIÈRES

5.4 Mémoire virtuelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30


5.4.1 Pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

ICT204 Introduction au système d’exploitation


Chapitre 1

Definition et historique

1.1 Introduction
Un système informatique a pour objectif d’automatiser le traitement de l’information. Il s’agit en effet d’un ensemble de
matériels et de logiciels (hardware et software) destinés à réaliser des tâches qui mettent en jeu le traitement automatique
de l’information. La représentation schematique d’un système d’information est la suivante :

Figure 1.1 – Système informatique

La partie matérielle (hardware) du système d’information est contituée des composants physiques (Ecran, clavier,
souris, ...), de la microarchitecture (registres, horloge, ...) et du langage machine.
La partie logicielle est constituée des programmes systèmes et des programmes applicatifs. L’objectif du logiciel est
d’offrir aux utilisateurs des fonctionnalités adaptées à leurs besoins et aussi de masquer les caractéristiques physiques
du matériel. Les programmes applicatifs concourent à la résolution des problèmes spécifiques des utilisateurs tandis que
les programmes systèmes (utilitaires et système d’exploitation) permettent plus le bon fonctionnement de la machine en
elle-même.
Dans le cadre de ce cours, nous nous focaliserons sur la partie logicielle du sistème informatique et plus spécifiquement
sur le sytème d’exploitation et son fonctionnement.

1.1.1 Qu’est-ce q’un système d’exploitation


Le bon fonctionnement d’un ordinateur est régit par les programmes qui y tournent. Autrement dit, sans programme,
l’ordinateur n’est voué à rien.
Le système d’exploitation est donc le programme de base de tout ordinateur ; En effet, il s’agit d’un ensemble de
programmes qui met en liaison les applications de l’utilisateur avec les ressources matérielles de l’ordinateur. Il assure le
lien entre le software et le hardware.
Un système d’exploitation a principalement deux fonction :

3
4/32 CHAPITRE 1. DEFINITION ET HISTORIQUE

1. Gestionnaire de ressources
2. Machine virtuelle
En tant que gestionnaire de ressources, le système d’exploitation permet entre autres :
— La gestion du/des processeurs(s).
— La gestion de la mémoire.
— La gestion des périphériques.
— ...
En tant que machine virtuelle, le système d’exploitation permet entre autres :
— Le chargement et le lancement des programmes d’applications.
— La gestion des processus et des fichiers.
— La protection contre les erreurs et la détection des erreurs.
— ...

1.1.2 Historique des systèmes d’exploitation


Les systèmes d’exploitation ont évolués avec les générations d’ordinateurs.

Première génération (Tubes électroniques) : pas de système réel - 1945-1955


Les machines de cette génération caractérisées par de très grandes tailles, très onéreuses et peu fiable n’avaient pas
de système d’exploitation. Les programmes étaient directement écris en langage machine,et une fois chargés en mémoire,
étaient exécutés et tout géré par une unité de commande. Le mode de fonctionnement ici consistait à réserver une tranche
de temps à chaque programmeur (Un seul programme en mémoire).

Seconde génération (Transistors) : Traitement par lots - 1955-1965


Le système d’exploitation par traitement par lot est connu comme l’ancêtre des systèmes d’exploitation. A cette généra-
tion, les machines étaient constituées des transistors dotés de bandes magnétiques. Bien que les machines étaient toujours
aussi énorme, elles étaient plus fiables. Le principe de fonctionnement de ce système était d’exécuter les programmes par
lots d’instructions.

Figure 1.2 – Traitement par lots

Inconvénients de ce systèm :
— Le processeur reste inutilisé pendant les opérations d’entrées/sorties.
— Le temps d’attente des résultats est trop long.
— Pas d’interaction avec l’utilisateur.

Troisième génération (Circuits intégrés) : multiprogrammation et traitement par lots - 1965-1980


Contrairement au système précédent où la mémoire n’avait qu’une seule partition (et donc ne pouvait contenir qu’un
travail à la fois), la mémoire de ce système est partitionnée en plusieurs parties (et donc peut contenir plusieurs travaux
à la fois, un dans chaque partition) ; Ce système est donc un système multitâche. Lorsqu’un travail demande une E/S (en
attente de la fin d’une E/S), le processeur est alloué à un autre travail en mémoire (le suivant). A la fin d’une E/S, une
interruption se produit et le système d’exploitation reprend le contrôle pour traiter l’interruption et lancer ou poursuivre
l’exécution d’un travail. Dès qu’un travail se termine, le système d’exploitation peut lancer le chargement, à partir du
disque, d’un nouveau travail dans la partition qui vient de se libérer.

ICT204 Introduction au système d’exploitation


5/32 CHAPITRE 1. DEFINITION ET HISTORIQUE

Figure 1.3 – Multiprogramtion et traitement par lots

Quatrième génération : Multiprogrammation à temps partagé - depuis 1980


Presque similaire au système précédent avec la différence que ce nouveau système introduit une technique de partage
de temps, ceci permettant une certaine équité en temps processeur pour chaque travail et permettant un temps de réponse
plus élevé.
Le processeur est alloué, à tour de rôle, pendant un certain temps (quantum) à chacun des travaux en attente d’exé-
cution. Au bout de ce temps, même si le travail en cours ne s’est pas terminé, son exécution est suspendue. Le processeur
est alloué à un autre travail.

1.1.3 Structure d’un système d’exploitation


Il existe plusieurs structure de système d’exploitation. Nous pouvons citer entre autres :
— Structure en couches.
— Modèle client/serveur
— Structure monolithique.
— ...

Structure en couches
Ici le système d’exploitation est organisé en couhes, les couches étant fonctionnellement liées (chaque couche utilise les
fonctions des couches inférieures).

Figure 1.4 – Structure en couches

ICT204 Introduction au système d’exploitation


6/32 CHAPITRE 1. DEFINITION ET HISTORIQUE

— Au plus bas niveau on trouve le noyau, l’interface entre le matériel et le logiciel. Il se charge, en utilisant les fonctions
fournies par le matériel, de gérer la UCT, les interruptions et les processus (la communication et la synchronisation).
Il doit entièrement résider en mémoire.
— Au second niveau, on trouve le gestionnaire de la mémoire qui se charge du partage de la mémoire entre les processus
en attente d’exécution.
— Au troisième niveau, on a le module de gestion des entrées/sorties qui se charge de gérer tous les périphériques
(clavier, écran, disques, imprimantes, etc.).
— Au quatrième niveau, on trouve le gestionnaire de fichiers qui se charge de la gestion de l’espace du disque, de la
manipulation des fichiers tout en assurant l’intégrité des données, la protection des fichiers, etc.
— Au quatrième niveau, on trouve le gestionnaire de fichiers qui se charge de la gestion de l’espace du disque, de la
manipulation des fichiers tout en assurant l’intégrité des données, la protection des fichiers, etc.

Modèle client/serveur
Dans le modèle client/serveur Le système d’exploitation est composé d’un noyau et d’un ensemble de serveurs. Le
noyau gère la communication entre les clients et les serveurs. Les clients sont les demandeurs de services. Par exemple,
pour demander un service, comme la lecture d’un bloc d’un fichier, un processus utilisateur (aussi appelé processus client)
envoie une requête à un processus serveur qui effectue le travail et renvoie une réponse. Les serveurs s’exécutent en mode
utilisateur. Ils ne peuvent donc pas accéder directement au matériel. Par conséquent, une erreur ou un bogue dans le
serveur de fichiers, par exemple, n’affectera pas, en général, l’ensemble de la machine. Les dégâts se limitent au serveur.

1.1.4 Appels système


Le processeur (CPU) est l’unité de l’ordinateur qui permet le traitement ou l’exécution des intructions. Il peut fonc-
tionner sous deux modes différents permettant la protection du système d’exploitation :
1. Le mode utilisateur (esclave).
2. Le mode noyau (superviseur, privilégié, maître).

Figure 1.5 – Architecture de base de Windows

Les programmes applicatifs sont exécutés en mode utilisateur et le code du système d’exploitation est exécuté en mode
noyau.
Le code qui s’exécute en mode noyau possède un accès ilimité au matériel et du coup peut exécuter n’importe quelle
instruction du processeur, et peut référencer n’importe quelle adresse mémoire. Tout incident qui se produirait donc sous
ce mode pourrait interrompe le fonctionnement de l’ordinateur.

ICT204 Introduction au système d’exploitation


7/32 CHAPITRE 1. DEFINITION ET HISTORIQUE

Les programmes applicatifs quant à eux s’exécutant en mode utilisateur ne disposent pas d’un accès direct au matériel
et donc aux emplacements mémoires. Mais cependant un programmes utilisateur voulant accéder aux ressources matérielles
doit passer par le système d’exploitation par le biais d’un appel système.
Un appel système est donc une interruption logitielles (TRAP) qui a pour rôle d’activer le système d’exploitation.
Il est lancé par un programme dit appelant, et permet de passer du mode utilisateur au mode noyau en vue d’effectuer
certaine tâches spécifiques (récupération des paramètres, vérification de la validité de l’appel, lancement de l’exécution
de la fonction demandée, récupération du résultat) et de retourner au programme appelant (avec un retour en mode
utilisateur).
Le tableau ci-dessus est la liste non exhaustive des appels systèmes Unix conformement à la norme Posix (ensemble
des procédures standard d’Unix).

Appels système Description


fork() Créer un processus
waitpid(), wait() Attendre la terminaison d’un processus
execve() exécuter un autre programme
exit() Terminer l’exécution
open() Créer ou ouvrir un fichier
close() Fermer un fichier
read() Lecture de données
write() Écriture de données
Iseek() Pointeur dans un fichier
stat() Obtenir l’état des attributs
mkdir() Créer un répertoire
rmdir() Éliminer un répertoire
link() Liens vers un fichier
unlink() Éliminer un fichier
mount() Monter un système de fichiers
unmount() Démonter un système de fichiers
chdir() Changer de répertoire
chmod() Changer les permissions d’accès
kill() Signaux
time() Obtenir le temps

ICT204 Introduction au système d’exploitation


Chapitre 2

GESTION DES PROCESSUS ET DES


THREADS

2.1 Définition et caractéristiques d’un processus


Un procéssus est un programme en cours d’exécution. Les procéssus sont caractérisés par plusieurs éléments qui peuvent
les différencier les uns des autres. Un procéssus est donc caractérisé entre autre par :
— Un identifiant, qui est unique à chaque processus. Il s’agit du PID.
— Un état. Celui-ci peut varier tout au long de l’exécution du processus.
— Un espace d’adressage (pile d’exécution, ...) et des ressources allouées (mémoire, fichiers, ...)
— Une priorité.
— Des informations relatives à son processus parent, aux éventuels processus fils, ...
— ...
Toutes les informations relatives à tous les processus sont contenues dans une table appelée table des processus. Elle
est créée par le système d’exploitation et chaque entrée est constituée d’un identifiant d’un processus auquel est associé
son bloc de contrôle (PCB). La figure ci-dessus illustre cette table :

2.2 Etats d’un processus et changement de contexte


Un processus, au long de son exécution peut passer par plusieurs états :
1. Prêt : en attente de la ressource processeur.
2. Exécution : possédant la ressource processeur.
3. Bloqué : en attente d’un énvènement.
Initialement, un processus est à l’état prêt. Il passe à l’état exécution, lorsque le processeur entame son exécution. Un
processus passe de l’état exécution à l’état prêt, lorsqu’il est suspendu provisoirement pour permettre l’exécution d’un
autre processus. Il passe de l’état exécution à l’état bloqué, si le processus ne peut plus poursuivre son exécution (demande
d’une E/S). Il se met alors en attente d’un événement (fin de l’E/S). Lorsque l’événement survient, il redevient prêt.
Une interruption est une suspension temporaire de l’exécution d’un processus au profis d’un autre. Dans un système
multiprogrammé, à temps paratagé ou à priorité par exemple, une interruption d’un processus peut survenir lorsque le
quantum de temps de celui-ci est atteint.
Plusieurs actions font suite à l’arrivée d’une interruption :
1. Passage du mode utilisateur au mode noyau.
2. Sauvegarde du contexte du processus interrrumpu.
3. Chargement du contexte du processus ayant fait appel d’interruption.
La figure suivante illustre le changement de contexte entre deux processus.

8
9/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

Figure 2.1 – Table de processus

Figure 2.2 – Principaux états d’un processuss

2.3 Création et manipulation de base d’un processus


2.3.1 Création
Le système d’exploitation fournit un ensemble d’appels système qui permettent la création, la destruction, la commu-
nication et la synchronisation des processus. Les processus sont créés et détruits dynamiquement.
Un processus peut créer un ou plusieurs processus fils qui, à leur tour, peuvent créer des processus fils sous une forme
de structure arborescente. Le processus créateur est appelé processus père.
Un processus fils créé peut partager certaines ressources comme la mémoire ou les fichiers avec son processus père
ou avoir ses propres ressources. Le processus fils peut exécuter le même programme que son père ou charger un autre
programme. Le processus père peut contrôler l’usage des ressources partagées et peut avoir une certaine autorité sur ses
processus fils. Un processus peut suspendre ou détruire ses processus fils et peut se mettre en attente de la fin de l’exécution

ICT204 Introduction au système d’exploitation


10/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

Figure 2.3 – Changement de contexte

de ses fils. L’espace d’adressage du processus fils est obtenu par duplication de celui du père.
Si la création d’un processus fils suspend l’exécution du père jusu’à sa terminaison, on dit que l’exécution est séquen-
tielle. MS-DOS est un exemple de sytème à exécution séquentielle.
Si la création d’un processus fils ne suspend pas l’exécution du père, on dit que l’exécution est asynchrone. Unix est
un exemple de système à exécution asynchrone.
Un processus se termine par une demande d’arrêt volontaire (appel système exit()) ou par un arrêt forcé provoqué par
un autre processus (appel système kill()). Lorsqu’un processus se termine toutes les ressources systèmes qui lui ont été
allouées sont libérées par le système d’exploitation.

2.3.2 Appels système


Il existe de nombreux appels système de gestion de processus. Nous presentons quelques uns en s’appuyant sur la
norme Posix du système Unix/Linux.

1. Appel système fork()


Cet appel système permet la création des processus fils. La création du nouveau processus fils est faite par duplication
du processus père. Cette duplication facilite donc la création et le partage des ressources, le fils héritant des résultats
des traitements déjà réalisés par le père. Cenpendant comment donc différencier le père et le fils ? La différence est
faite à partir de la valeur de retour de fork() qui est :
— 0 pour le processus fils.
— Strictement positive pour le processus père. Cette valeur positive représente le pid du processus fils.
— Négative si la création de processus a échoué ; Ceci pourrait arriver par exemple si l’espace mémoire n’est pas
suffisante pour acceuillir un nouveau processus ou alors si le nombre maximal de création autorisé est atteint.
Remarques :
— Le tout premier processus qui est lancé au démarrage du système d’exploitation est le processus init dont le
pid est 1. Tout processus possède donc un père, à l’exception du processus init. Si un processus perd son père,
c’est-à-dire si son père termine son exécution, alors, il est adopté par le processus init.
— L’appel système getpid() permet de récupérer le pid d’un processus et getppid() permet de récupérer le pid de
son père.

Quelques programmes utilisant fork()

ICT204 Introduction au système d’exploitation


11/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

Figure 2.4 – fork()

# include <stdio.h>
# include <sys/types.h> // pour fork ()
# include <unistd.h>
int main(){
int fils_pid ;
if((fils_pid = fork())==0){
printf("Je suis le fils avec pid %d \n", getpid()) ;
}else{
if(fils_pid > 0){
printf("Je suis le père avec pid %d \n", getpid()) ;
}
}
return 0 ;
}

# include <stdio.h>
# include <sys/types.h>
# include <unistd.h>
int a=20 ;
int main(int argc, char *argv) {
pid_t x ;
switch (x = fork()) {
case -1 : // le fork a échoué
perror("le fork a échoué !") ;
break ;
case 0 : // seul le processus fils exécute ce < case >
printf("ici processus fils, le PID %d.\n ", getpid()) ;
a += 10 ;
break ;
default : // seul le processus père exécute cette instruction
printf("ici processus père, le PID %d.\n", getpid()) ;
a += 100 ;
}
printf("Fin du Process %d. avec a = %d.\n", getpid(), a) ;
return 0
}

2. Appels système exec()


Le programme exécuté par un processus peut être remplacé par un autre, ceci se faisant par le biais de la famille
d’appels système exec. Ces appels système remplacent donc le processus courant par un nouveau processus construit

ICT204 Introduction au système d’exploitation


12/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

à partir d’un fichier ordinaire exécutable.


En cas de succès d’un appel système exec, l’exécution de l’ancien code est abandonné au profit du nouveau ; Ainsi
l’image mémoire du processus est écrasé par la nouvelle image mémoire d’un processus exécutable, cependant le
pid ne change pas.
En cas d’échec d’un appels système exec, le processus poursuit l’exécution de son code à partir de l’instruction qui
suit l’appel.
Ces appels système sont les suivants :
— int execl(const char *path, const char *argv, ...) : permet de passer un nombre fixé de paramètres au
nouveau programme.
— int execv(const char *path, const char *argv[]) : permet de passer un nombre libre de paramètres au
nouveau programme.
— int execle(const char *path, const char *argv, const char *envp[]) : même fonctionnement qu’execl()
avec en plus, un argument envp qui représente un pointeur sur un tableau de pointeurs sur des chaînes de
caractères définissant l’environnement.
— int execlp(const char *file, const char *argv, ...) : Interface et action identiques à celles d’execl(), mais
la différence vient du fait que si le nom du fichier n’est pas un nom complet — par rapport à la racine — le
système utilisera le chemin de recherche des commandes — les chemins indiqués par la variable PATH — pour
trouver dans quel répertoire se trouve le programme.
— int execvp(const char *file, const char *argv[]) : Interface et action identiques à celles d’execv(), mais la
différence vient du fait que si le nom de fichier n’est pas un nom complet, la commande utilise les répertoires
spécifiés dans PATH.

3. Les appels système wait(), waitpid() et exit()


Ces appels système permettent à un processus père d’attendre la fin d’un de ses processus fils et de récupérer son
status de fin. Ainsi, un processus peut synchroniser son exécution avec la fin de son processus fils en exécutant
l’appel système wait().

#include <sys/wait.h>
int wait (int *status) ;
int waitpid(int pid, int *status, int options) ;
void exit(int return_code) ;

— wait() : Permet à un processus père d’attendre jusqu’à ce qu’un processus fils termine son exécution. Il retourne
l’identifiant du processus fils et son état de terminaison dans & status.
— waitpid() : Permet à un processus père d’attendre jusqu’à ce que le processus fils numéro pid termine. Il retourne
l’identifiant du processus fils et son état de terminaison dans & status.
— exit() : Permet de finir volontairement l’exécution d’un processus et donne son état de terminaison.
Les appels système wait() et waitpid() ont un grand intérêt pour le système. Lorsqu’un processus fils termine son
exécution (exit()) et que son père n’est pas au courant de sa terminaison (c’est-à-dire que son père n’a pas fait de
de wait() ou de waitpid()), alors ce processus fils devient un processus zombie. Un processus zombie bien que
n’utilisant pas les ressources du noyau, est toujours présent dans la table des processus jusqu’à ce que son père
exécute wait() ou waitpid().

2.3.3 Terminaison de processus


Un processus se termine soit par une demande d’arrêt volontaire (exit()), soit par un arrêt forcé provoqué par un autre
processus (kill()) soit par une erreur. Lorsqu’un processus se termine :
— Son état de terminaison est enregistré dans son PCB.
— La plupart des ressources qu’utilisait le processus sont libérées.
— Le processus passe à l’état zombie.
Le pid et le PCB d’un processus sont conservés jusqu’à ce que son père récupère son état de terminaison (wait() et
waitpid()) et de ce fait le processus disparait totalement du système.

ICT204 Introduction au système d’exploitation


13/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

2.4 Les threads


2.4.1 Définition et caractérisques
Le modèle de processus décrit précédemment est un programme qui s’exécute selon un chemin unique, en d’autres
termes, ils ont un seul flot de contrôle unique (un thread), et utilise un seul compteur ordinale. Cependant dans les
système d’exploitation modernes, à un processus peut être associé plusieurs chemins d’exécution (multithreads), ceci
permettant l’exécution simultanée des parties d’un même processus.

Figure 2.5 – Threads. vs processus

Un thread est donc une unité d’exécution rattachée à un processus, chargé d’exécuter une partie du programme
du processus. Dans un système multithreading, un processus est vu comme un ensemble de ressources partagées (code
exécutable, segement de données, fichiers, périphérique, ...) entre les threads.
Lorsqu’un processus est crée, un seul fil d’exécution (thread principal) est associé au processus et ce dernier exécute
la fonction principale du processus. Ce thread en crééra donc d’autres. Chaque thread possède :
— Un identificateur unique : tid.
— Une pile d’exécution.
— Des registres (un compteur ordinal).
— ...

Figure 2.6 – Threads et ressources

2.4.2 Avantages des threads


Les threads ou processus legers avec plusieurs flots de contrôles présentent plusieurs avantages :
— La réactivité : Le processus peut continuer à s’exécuter même si certaines de ces parties sont bloquées.
— Le partage de ressources : ceci facilite la coopération et améliore la performance.
— Economie d’espace mémoire et de temps. Il faut moins de temps pour créer un thread, terminer un thread, changer
de contexte entre deux threads de même processus.

ICT204 Introduction au système d’exploitation


14/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

Implémentation des threads


L’implémentation du multitreading (multiflot) est fortement lié au système. Le multithreading peut être implémenté :
1. Au niveau utilisateur.
Les threads utilisateurs sont implantés dans une bibliothèque (niveau utilisateur) qui fournit un support pour les
gérer. Le noyau gère les processus (table des processus) et ne se préocupe pas de l’existence des threads . Lorsque
le noyau alloue le processeur à un processus, le temps d’allocation du processeur est reparti entre les différents
threads du processus (modèle plusieurs à un), cette répartition n’étant pas gérée par le noyau.

Figure 2.7 – Threads utilisateur

Avantages :
— Ils sont généralement créés et gérés rapidement.
— Ils facilitent la portabilité, du fait qu’ils ne ne dépendent pas du noyau.
Inconvénients :
— A tout instant, au plus un thread du processus est en cours d’exécution, ce qui rend cette implémentation non
intéressante pour les systèmes multiproceseurs.
— Si un thread d’un processus se bloque, tout le pocessus est bloqué.

2. Au niveau noyau.
Les threads noyau sont directement supportés par le noyau du système d’exploitation. Il se charge de leur gestion, du
temps processeur alloué à chaque thread. Dans les systèmes mutiprocesseurs, cette implémentation est intéressant,
car chaque processeur est attribué à un thread (modèle un à un). Si un thread d’un processus est bloqué, un autre
thread de ce processus peut être élu par le noyau.
Inconvénients :
— Au niveau de la performance, la gestion est plus coûteuse.
— Portabilité : les programmes utilisant les threads noyau sont moins portables que ceux utilisant les threads
noyau.
3. Aux deux niveaux (hybride).
Il s’agit du modèle plusieurs à plusieurs. Il sont implantés par le système d’exploitation (utilisateur et système).
Les threads utilisateur sont associés à des threads système. La plupart des tâches gestion s’effectuent sous le mode
utilisateur.

2.4.3 Appels system de gestion des threads


Il existe plusieurs opérations (appels systèm) pour la gestion des threads (creation, terminaison, suspension, relance,
...).
Pour le cas d’étude du système Linux présenté dans ce cours, il est improtant de comprendre qu’il y a pas de distinction
entre les processus et les threads. Linux implémente le modèle un à un. Un thread étant un processus qui partage certaines
ressources avec le processus créateur. Pour la gestion Posix de threads, Linux utilise la bibliothèque pthread.

ICT204 Introduction au système d’exploitation


15/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

Figure 2.8 – Threads noyau

— Création des threads


int pthread_create (pthread_t *thread , pthread_attr_t *attr, void *nomfonction, void *arg ) ;
pthread_create() permet la création d’un thread, celui-ci exécute la fonction nomfonction, avec l’argument arg et
les attributs attr (ils permettent de spécifier la taille de la pile, la priorité, ...).
En cas de succès, l’appel retourne la valeur 0. En cas d’échec, l’appel retourne une valeur non nulle identifiant
l’erreur.

— Suspension de Threads
int pthread_join(pthread_t *thid, void **valeur_de_retour) ;
pthread_join() suspend l’exécution d’un processus léger jusqu’à ce que termine le processus léger avec l’identificateur
thid. Il s’agit de l’équivalent de waitpid(). valeur_de_retour sert à récupérer la valeur de retour l’état de terminaison
du processus léger.
pthread_tpthread_self(void) ; Cet appel retourne le tid du thread appelant.

— Terminaison de threads
void pthread_exit(void *valeur_de_retour) ;
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) ;
pthread_exit() permet à un processus léger de terminer son exécution, en retournant l’état de terminaison.
pthread_attr_setdetachstate() sert à établir l’état de terminaison d’un processus léger :
1. Si detachstate = PTHREAD_CREATE_DETACHED, le processus léger libérera ses ressources quand il ter-
minera
2. Si detachstate = PTHREAD_CREATE_JOINABLE le processus léger ne libérera pas ses ressources. Il sera
donc nécessaire d’appeler pthread_join().

Quelues programmes de manipulation des threads

ICT204 Introduction au système d’exploitation


16/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

# include <stdio.h>
# include <sys/types.h>
# include <unistd.h>
# include <pthread.h>
int glob=0 ;
void* increment(void *) ;
void* decrement(void *) ;
int main() {
pthread_t tid1 , tid2 ;
printf(" ici main[%d], glob = %d", getpid(),glob) ;
// création d’un thread pour increment
if(pthread_create(tid1, NULL, increment, NULL) != 0)
return -1 ;
printf("ici main : creation du thread[%d] avec succès \n", tid1) ;
// création d’un thread pour decrement
if ( pthread_create(tid2, NULL, decrement, NULL) != 0)
return -1 ;
printf("ici main : creation du thread [%d] avec succès \n", tid2 ) ;
// attendre la fin des threads
pthread_join(tid1,NULL) ;
pthread_join(tid2,NULL) ;
printf("ici main : fin des threads, glob = %d \n",glob) ;
return 0 ;
}
void* increment(void *) {
int dec=2 ;
sleep (10) ;
glob = glob + dec ;
printf (" ici decrement[%d], glob = %d", getpid(), glob) ;
pthread_exit(NULL) ;
}
void* decrement(void *) {
int dec=1 ;
sleep (1) ;
glob = glob - dec ;
printf (" ici decrement[%d], glob = %d", getpid(), glob) ;
pthread_exit(NULL) ;
}

Le programme doit être compilé avec la librairie -lpthread. L’exécution en tâche de fond de pthread-pid.
Une trace d’exécution de ce programme est la suivante :

ICT204 Introduction au système d’exploitation


17/32 CHAPITRE 2. GESTION DES PROCESSUS ET DES THREADS

# include <stdio.h>
# include <sys/types.h>
# include <unistd.h>
# include <pthread.h>
void *threadf unction(void ∗ arg);
char message[] = "Hola mundo" ;
int main() {
int res ;
pthread_t a_thread ;
void *threadr esult;
res = pthreadc reate(a_thread, N U LL, thread_f unction, (void∗)message);
if(res != 0) {
perror("Thread creation failed ") ;
exit (EXIT_FAILURE) ;
}
printf ("En attente que le thread termine..." ) ;
res = pthread_join(a_thread, threadr esult);
if ( res != 0){
perror("Echec dans l’union du thread) ;
exit (EXIT_FAILURE) ;
}
printf ("Thread termine %s", (char *)thread_result) ;
printf("Le message est %s", message) ;
exit (EXIT_SUCCESS) ;
return 0 ;
}
void *thread_function(void *arg) {
printf ("La fonction du thread demarre. L’argument est ’%s’", (char *) arg) ;
sleep (5) ;
strcpy(message, "Adios !") ;
pthread_exit("Merci par le temps de CPU") ;
}

ICT204 Introduction au système d’exploitation


Chapitre 3

ORDONNANCEMENT DES PROCESSUS

3.1 Introduction
Nous avions précédement défini un processus comme étant un programme en cours d’exécution. Il peut être prêt (en
attente de la ressource processeur), bloqué (en attente dun évènement d’E/S), ou alors en exécution (utilisant la ressource
processeur).Pour être dans l’un de ses états, le processus doit préalablement être présent en mémoire. Dans les système
multi-utilisateurs à temps partagé, plusieurs processus peuvent être présent dans la mémoire en attente d’exécution,
autrement dit en attente de la ressource processeur. Comment donc se fait l’allocation du processeur entre les processus
prêts ? L’objectif principal de ce chapitre est de pouvoir répondre à cette question.

3.2 Définitions de base


Un système multitâche préemptif est un système dans lequel il est possible, à tout moment, de suspendre l’exécution
d’un processus en lui enlevant le processeur au profis d’un autre. Dans un tel système, plusieurs applications peuvent
fonctionner en simultanée.
A côté des systèmes multitâches préemptifs, il existe des systèmes multitâches coopératifs où plusieus applications
peuvent fonctionner en simultanée tout en occupant la mémoire, mais sans aucun contrôle du système d’exploitation, au
risque de bloquer tout le système.
L’ordonnancement est un procédé qui consiste à organiser dans le temps la réalisation d’une suite de tâches. En d’autre
terme, il s’agit d’un mécanisme qui consiste à planifier l’allocation des ressources aux différents processus en cours. Ce
mécanisme est assuré par l’odonnaceur (scheduler) qui est composant du noyau du système d’exploitation dont le rôle
principal consiste à :
1. Faire le choix du processus à exécuter par le processeur.
2. Définir le temps d’allocation du processeur au processus choisi.
De facon plus détaillée, dans un système multi-utilisateurs, l’ordonnanceur a pour objectifs de :
— S’assurer que chaque processus à l’état prêt (attente d’exécution) passe à un moment donné en exécution.
— Minimiser le temps de reponse.
— S’assurer de l’utilisation à 100 % du processeur.
— S’assurer d’une utilisation équilibrée des ressources.
— ...

3.2.1 Types d’ordonnanceurs


Il existe trois type d’ordonnanceurs ayant des rôles bien spécifique :
1. A long terme.
Il a pour rôle de sélectionner les programmes à admettre dans le système pour exécution. Les programmes admis
deviennent des processus à l’état prêts (non actifs). L’admission dépend de la capacité du système (degré de
multiprogrammation) et du niveau de performance requis.

18
19/32 CHAPITRE 3. ORDONNANCEMENT DES PROCESSUS

2. A moyen terme
Il décide lesquels des processus précédemment sélectionés doivent aller en mémoire (principale). Il peut aussi
transférer les processus de la mémoire principale (processus prêt actif) à la mémoire secondaire (processus prêt non
actif). Il effectue ses tâches de géstion en fonction du degré de multiprogrammation du système, et aussi en base
aux requêtes d’E/S des périphériques.
L’ordonnanceur à moyen terme introduit le concept d’états actifs et non actifs et deux états supplémentaires : prêt
en suspension et attente en suspension.
Un processus est donc prêt en suspension lorsqu’il est déjà prêt à sexécuter (il a déjà été sélectionner par l’ordon-
nanceur à long terme), mais cependant ne se trouve pas encore en mémoire principale ; Un tel processus ne peut
pas se voir attribuer le processeur.
L’attente en suspension est l’état d’un processus qui attend. Dans cet état, le processus se trouve en mémoire
secondaire.
3. A court terme
Il gère la file d’attente des processus prêts (actifs), en choisissant quel processus doit passer en exécution, et par
conséquent se charge des changements de contexte.

La figure ci-dessus nous présente le modèle des états actifs et non actifs des processus.

Figure 3.1 – Modèle des états actifs et non actifs d’un processus

3.3 Politiques d’ordonnancement non préemptif


L’ordonnancement non préemptif est encore dit sans requisition, c’est-à-dire une fois que l’ordonnanceur fait un choix
d’octroiyer le processeur à un processus, celui-ci fini entierement de s’exécuter ou se bloque avant de libérer le processeur.
Les politiques d’ordonnancement les plus implémentées sont les suivantes :
1. Le premier arrivé, premier servi (PAPS). Dans cette politique, un file de processus prêts est mise su pied et le
processus en tête de file se voit attribué le processeur.
2. Le plus court d’abord (SJF : short job first). Cette politique consiste à choisir parmi les processus à exécuter, le
plus court, c’est-à-dire, celui dont le temps d’exécution est moindre. L’ordonnanceur attribue donc le processeur à
ce processus.

La comparaison entre différentes politiques d’ordonnancement peut être faite à partir de certaines valeurs :
— Le temps de séjour. Le temps de séjour d’un processus (temps de rotation ou de virement) est l’intervalle de
temps entre la soumission du processus et son achèvement.
— Le temps d’attente. Le temps d’attente d’un processus est la différence entre le temps de séjour et le temps
d’exécution du processus.

ICT204 Introduction au système d’exploitation


20/32 CHAPITRE 3. ORDONNANCEMENT DES PROCESSUS

Exemple 1 : Considérons cinq travaux A, B, C, D et E, dont les temps d’exécution et leurs arrivages respectifs
sont donnés dans le tableau ci-desous. Faire un schéma qui illustre son exécution et calculer le temps de séjour de
chaque processus, le temps moyen de séjour, le temps d’attente et le temps moyen d’attente en utilisant les politiques
d’ordonnancement :
1. Premier arrivé premier servi (PAPS).
2. Le plus court d’abord (SJF).
Processus T’emps d’exécution Temps d’arrivage
A 3 0
B 6 1
C 4 4
D 2 6
E 1 7

3.4 Politiques d’ordonnancement préemptif


Les politiques d’ordonnancement définies précédemment présentent quelques inconvénients :
— Dans le cas du premier arrivé, premier servi, un processus ayant besoin de beaucoup de temps processeur pour son
exécution pourrait s’accaparer du processeur s’il arrive avant un processus qui a besoin de peu de temps.
— Dans le cas du plus court d’abord, un processus ayant besoin de beaucoup de temps processeur pour son exécution
pourrait ne jamais s’exécuter si les processus qui ont besoin de peu de temps arrivent toujours avant qu’il ne soit
en exécution.
Pour réduire au mieux ces inconvénients, il convient d’ordonnancer de manière préemptive ou avec réquisition les
processus. Cette réquisition du processeur sera donc initiée par un signal d’interruption, provoqué par une horloge, qui
activera le système d’exploitation afin qu’il reprenne la main et attribue le processeur à un autre processus de la file
d’attente des processus prêts. Avant la suspension d’un processus par le système d’exploitation, il sauvegarde d’abord
son contexte, une fois ceci fait, il charge le contexte du nouveau processus élu : c’est la commutation de contexte ou le
changement de contexte.
Le temps d’allocation du processeur à un processus est appelé quantum. Le temps de commutation doit être rapide,
celui-ci doit être nettement inférieur à celui du quantum.

3.4.1 Ordonnancement du plus petit temps de séjour


Il s’agit de l’algorithme SRT (Short Remaining Time), qui est la version préemptive de la politique du plus court
d’abord. D’après cette politique, l’attente d’un processus ne devrait pas être longue si son temps d’exécution est court.
Ainsi donc, à chaque arrivée d’un processus dont le délai d’exécution est inférieur au délai de celui en cours d’exécution,
il y a interruption, l’ordonnanceur réquisitionne le processeur et l’attribue à ce dernier.

3.4.2 Ordonnancement circulaire (Round robin)


Pour son fonctionnement, l’algorithme utilise une file du type FIFO (First In First Out) dans laquelle il mémorise la
liste des processus en attente d’exécution. L’ordonnanceur alloue le processeur au processus en tête de file, pendant un
quantum de temps. Si le processus se bloque ou se termine avant la fin de son quantum, le processeur est immédiatement
alloué à un autre processus (celui en tête de file). Si le processus ne se termine pas au bout de son quantum, son exécution
est suspendue. Le processeur est alloué à un autre processus (celui en tête de file). Le processus suspendu est inséré en
queue de file. Les processus qui arrivent ou qui passent de l’état bloqué à l’état prêt sont insérés en queue de file.
Remarque : Un quantum trop petit provoque trop de commutations de processus et abaisse l’efficacité du processeur.
Un quantum trop élevé augmente le temps de réponse des courtes commandes en mode interactif.

Exemple 2 : Soient deux processus A et B prêts tels que A est arrivé en premier suivi de B, 2 unités de temps
après. Les temps de l’UCT nécessaires pour l’exécution des processus A et B sont respectivement 15 et 4 unités de temps.
Le temps de commutation est supposé nul. Calculer le temps de séjour de chaque processus A et B, le temps moyen
de séjour, le temps d’attente, le temps moyen d’attente, et le nombre de changements de contexte pour les politiques
d’ordonnancement :

ICT204 Introduction au système d’exploitation


21/32 CHAPITRE 3. ORDONNANCEMENT DES PROCESSUS

Figure 3.2 – Ordonnancemet circulaire

1. SRT.
2. Round robin (quantum = 10 unités de temps).
3. Round robin (quantum = 3 unités de temps).

Exemple 3 : Soient trois processus A, B et C. Le processus A arrive en premier suivi de B (3 unités de temps après),
puis C (4 unités de temps après B). On suppose que l’exécution du processus A nécessite 8 unités de temps de l’UCT.
L’exécution du processus B nécessite dans l’ordre 5 unités de temps de l’UCT, 2 unités de temps d’E/S et 3 unités de
temps de l’UCT. L’exécution du processus C nécessite 4 unités de temps UCT. Le quantum est de 3 unités de temps. Le
temps de commutation est de 1 unité de temps.
1. Montrer comment les trois processus vont utiliser le processeur, dans le cas d’un ordonnancement circulaire.
2. Calculer le temps de séjour pour chacun des trois processus et le temps de séjour moyen des trois processus.
3. Que se passe-t-il, si on augmente la valeur du quantum ? (Qt = 5).
4. Que se passe-t-il, si on diminue la valeur du quantum ? (Qt = 2).

3.4.3 Ordonnancement avec priorité


Nous pouvons nous retrouver dans des situations où le résultat attendu de l’exécution d’un processus quelconque A
soit d’une très grande importance par rapport à celui d’un autre processus B. Dans ce cas, on privilégiera l’exéclution du
processus A par rapport au à celle du processus B. Du fait de son caractère d’équitabilité (partage équitable du processeur),
ni l’ordonnancement du plus petit temps de séjour, ni l’ordonnancement circulaire ne peuvent répondre à un tel besoin,
c’est la raison pour laquelle a été introduit l’ordonnancement à priorité qui tient compte du privilège accordé à chaque
processus.
Dans l’ordonnancement à priorité, à chaque processus prêt est attribué une priorité et le processus dont on privilégie
l’exécution est celui de plus grande priorité. Les processus de même priorité sont regroupés dans une file du type FIFO.
Donc il y a autant de files qu’il y a de niveaux de priorité. L’ordonnanceur choisit le processus le plus prioritaire qui
se trouve en tête de file. Les processus de même priorité (appartenant à la même file) sont le plus souvent ordonnancés
circulairement.

Figure 3.3 – Ordonnancemet avec priorité

Chaque fois qu’un processus s’exécute sa priorité est revue à la baisse. La priorité du processus en cours est comaprée
régulièrement à celle du processus prêt le plus prioritaire, une fois qu’elle devient inférieure, la commutation a lieu et le
processus suspendu est inséré en queue de file correspondant à sa nouvelle priorité.

Remarque : l’attribution et l’évolution des priorités dépendent des objectifs fixés et aussi des paramètres divers. Nous
pouvons par exemple avoir comme priorité le rapport du quantum et de la durée d’exécution restante pour le processus.

ICT204 Introduction au système d’exploitation


22/32 CHAPITRE 3. ORDONNANCEMENT DES PROCESSUS

Exemple 4 : Considérons quatre travaux A, B, C, et D, dont les temps d’exécution, la priorité et leurs arrivages
respectifs sont donnés dans le tableau ci-desous. Faire un schéma qui illustre leur exécution et calculer le temps de séjour
de chaque processus, le temps moyen de séjour, le temps d’attente et le temps moyen d’attente en utilisant l’ordonnancement
à priorité.

Processus T’emps d’exécution Temps d’arrivage Priorité


A 5 0 4
B 4 2 2
C 2 2 6
D 4 4 3

ICT204 Introduction au système d’exploitation


Chapitre 4

COMMUNICATION SYNCHRONISATION
INTERPROCESSUS

4.1 Introdution
La communication interprocessus est un mécanisme dans lequel plusieurs processus s’exécutant en parallèle ou en
pseudo-parallèle coopèrent en s’échangeant les informations dans un but de résourdre des problèmes plus ou moins com-
plexes. Les systèmes d’exploitaton actuels offrent cette possbilité à plusieurs processus et threads concurrents de copérer.
Ceux-ci peuvent s’exécuter sur un même ordinateur (monoprocesseur ou multipocesseur) ou sur des ordinateurs différents
en réseau. Il existe plusieurs mécanismes de communication interprocessus :
— Les données communes (variables, fichiers, segment de données).
— Les signaux
— Les messages
— Les tubes de communication
— Les sockets

4.2 Les données communes


Les processus se partagent un ensemble de données communes qui sont soit en mémoire (variables ou segments de
données) ou sur disque (fichiers), et aussi des ressources (imprimante, processeur, ...). Chaque processus peut accéder en
lecture ou en écriture à cet ensemble de données appelé espace de donnée commun. Cet accès commun à cet espace de
données commun peut poser des problèmes d’accès concurents ; Si plusieurs processus lisent ou modifient des données
partagées, cela peut conduire à des résultats imprévisibles (les resultats peuvent être érronés pour certains) car dépendant
fortement de l’ordonnancement de ces processus. La mauvaise gestion des transactions sur les données d’une base de
données entrainerait par exemple des problème de perte de mise à jour, ou de lecture impropre par exemple.

Figure 4.1 – Conflits d’accès

23
24/32 CHAPITRE 4. COMMUNICATION SYNCHRONISATION INTERPROCESSUS

Pour résoudre ces problèmes de confits d’accès, il s’avère donc nécessaire de contrôler les accès concurrents aux données
partagées au travers de la synchronisation des processus.

NB : La suite de ce chapitre se fera sous forme d’exposés qui porterons sur des sujets relatifs au présent chapitre.

ICT204 Introduction au système d’exploitation


Chapitre 5

GESTION DE LA MEMOIRE

5.1 Introduction
La mémoire principale est le lieu de stockage des programmes en cours d’exécution. Le besoin continuellement gran-
dissant de la mémoire par les programmes, necessite une gestion optimale de celle-ci. Le gestionnaire de mémoire est la
partie du système d’exploitation qui gère la hiérarchie de la mémoire installée sur un ordinateur.

Figure 5.1 – Hiérarchie de la mémoire

L’espace d’adressage logique (ou virtuel) est un ensemble d’adresses pouvant être générées par un programme
(compilation ou édition des liens) ; Se sont des adresses manipulées par l’unité centrale.
L’espace d’adressage physique est un ensemble d’adresses physiques correspondant à un espace d’adressage lo-
giques. Il s’agit des adresses manipulées par la mémoire.
Dans sa gestion de la hiérarchie de la mémoire, le gestionnaire de la mémoire a deux objectifs principaux :
1. Le partage de la mémoire principale entre les programmes et les données des processus prêts.
2. La mise en place des mécanismes de calcul d’adresse, ceci permettant de passer de l’adresse virtuelle à l’adresse
physique et vice versa.

Pour atteindre ces objectifs, le gestionnaire de la mémoire doit remplir plusieurs tâches :
— Connaître l’état de la mémoire (quelles sont les parties libres et occupées ?).
— Allouer de la mémoire à un processus avant son exécution.
— Récupérer l’espace alloué à un processus dès la fin de son exécution.
— Traiter les va-et-vient (swaping) entre le disque et la mémoire principale (lorsque cette dernière ne peu pas contenir
tous les processus).
— Posséder un mécanisme de calcul d’adresse physique (absolue) à partir des adresses virtuelles (logiques ou relatives)
générées par le programmes (compilation ou édition des liens). Le calcul d’adresse est réalisé par le matériel, dans
un but de ne pas ralentir l’accès à la mémoire.

25
26/32 CHAPITRE 5. GESTION DE LA MEMOIRE

5.2 Monoprogrammation
Dans les systèmes monoprogrammé, il n’est possible d’avoir qu’un seul programme utilisateur en mémoire à la fois. Le
gestionnaire de la mémoire partage donc la mémoire entre un programme utilisateur et le système d’exploitation. Cette
gestion de la mémoire est assez simple :
— L’utilisateur entre une commande sur un termina ;
— Le système d’exploitation charge le programme demandé en mémoire et ce dernier est exécuté ;
— L’exécution une fois terminée, le système d’exploitation afiche une invitation sur le terminal et attend la commande
suivante pour charger un nouveau processus qui remplace le précédent.
Bien qu’étant très simple à gérer, la gestion de la mémoire dans les système monoprogrammé nécessite la protection
du système d’exploitation ; Il faudrait donc s’assurer qu’un programme utilsateur n’écrase pas le système d’exploitation.
Pour ce faire, on sauvegarde dans un registre (registre limite), l’adresse à partir de laquelle commencerons les instructions
et les données des programmes utilisateurs. Donc chaque adresse générée par un programme est comparée avec le contenu
de ce registre ; Si la valeur de l’adresse générée est supérieure ou égale à celle du registre, le programme est chargé en
mémoire, sinon, le programme n’est pas chargé et un message d’erreur est généré.

Figure 5.2 – Registre limite

5.3 Multiprogrammation
La multiprogrammation autorise l’exécution de plusieurs processus utilisateurs. Dès qu’un procssus se bloque (en
attente d’E/S), un autre processus prêt peut devenir actif. Ceci permet donc d’optimiser le taux d’utilisation du processeur.
Cette technique exige que plusieurs programmes soient chargés en mémoire à un instant donné. La méméoire est
donc partagée entre le système d’exploitation et plusieurs programmes utilisateurs. Plusieurs techniques de gestion de la
mémoire peuvent donc être implémentées :
— Partitions fixes.
— Partitions variables.
— Le swaping.
— Gestion de la mémoire par table de bits.
— Gestion de la mémoire par listes chaînées.

5.3.1 Multiprogrammation à partitions fixe.


Cette technique de gestion de la mémoire consiste à diviser la mémoire en n partitions, chacune pouvant contenir
un seul processus. Les partitions peuvent être de tailles égales ou inégales. Le partitionnement se fait au démarrage du
système. La taille des partitions et leur nombre ne changent pas au cours de la session (MFT : Multiprogramming
with a Fixed number of Tasks). Nous pouvons avoir deux types de représentations de files d’attentes des processus
désirant aller en mémoire :
1. File multiple. Avec cette représentation, à chaque partition est associée une file d’attente. Un processus voulant
être chargé en mémoire est présente dans la file d’attente correspondant à la plus petite partition pouvant la
contenir. L’inconvénient de cette représentation est que à un moment donné, nous pouvons avoir les files d’attente

ICT204 Introduction au système d’exploitation


27/32 CHAPITRE 5. GESTION DE LA MEMOIRE

des petites partitions pleine, tandis que les files d’attente des grandes sont vides ; Dans ce cas les tâches nécessitant
de petites tailles de mémoire attendrons pendant longtemps avant d’accéder en mémoire pourtant la mémoire
pourrait contenir des partitions inutilisées.

2. File unique. Pour palier au problème présenté précédemment, on peut utiliser une file d’attente unique. Dans
ce cas, dès qu’une partition est libre, tout processus pouvant y tenir et se trouvant en tête de file est chargé.
L’inconvénient de cette technique est le gaspillage de la mémoire ; En effet un petit processus peut se voir allouer
une grande partition. Pour éviter ce gaspillage, la getion de la file unique n’est le FIFO, mais dès qu’une partition
devient libre, on parcourt la file d’attente à la recherche du plus grand processus pouvant y tenir et on charge
ce dernier dans cette partition. Pour éviter que les petits processus ne soient pénalisés, à chaque petit processus
on attribue un compteur initialisé à 0, ce compteur est incrémenté d’une unité à chaque fois que le processus est
ignoré. Un processus ne pourra pas être ignoré k fois, où k est un paramètre fixé.

Figure 5.3 – Partitions fixes

5.3.2 Fragmentation
Dans la multiprogrammation à partitions fixes, les processus pouraient ne pas (et c’est le cas très souvent) occuper tout
l’espace de la partition qui lui est attribuée, laissant donc de la mémoire non utilisée dans la dite partition. Il peut aussi
arrivé que toutes les partitions de la mémoire ne puisse pas être utilisées. Ce phénomène de présence d’espaces inutilisés,
aussi bien dans une partition et aussi due à la non allocation d’une partition à un processus est appelé fragmentation. On
parle de fragmentation interne dans le premier cas et de fragmentation externe dans le deuxième.

Figure 5.4 – Fragmentation

5.3.3 Swaping (Va-et-vient)


Dans la multiprogrammation à partitions fixes décrite précédemment, le nombre de processus pouvant être exécutés
simultanément est conditionné par le nombre de partitions disponible en mémoire. De plus un autre problème est celui de
la détermination de la taille des partitions optimale qui minimiserait la fragmentation (interne et externe) de la mémoire.

ICT204 Introduction au système d’exploitation


28/32 CHAPITRE 5. GESTION DE LA MEMOIRE

Supposons qu’un système simple a une mémoire de 120 Ko, et que tous les processus utilisent moins de 20 Ko, sauf un
qui utilise 80 Ko et qui s’exécute une fois par jour. Évidement pour permettre à tous les processus de s’exécuter le système
doit posséder au moins une partition de 80 Ko, et les autres partitions de 20 Ko. Ainsi le système utilisera seulement une
fois par jour les 80 Ko, et le reste du temps elle sera inutilisée, créant donc avec une fragmentation externe de 80 Ko ;
ou bien elle sera occupée partiellement par un processus de 20 Ko, créant de ce fait une fragmentation interne de 60 Ko.
Dans les deux cas on n’utilise que la moitié de la mémoire du système. La technique de vat-et-vient (ou swaping) apporte
une solution à ces problèmes.

Les partitions au lieu d’être de taille fixe ne le sont plus, mais leurs tailles et leur nombre sont variables (MVT :
Multiprogramming with a Variable number of Tasks). Lorsque tous les processus ne peuvent pas tenir simultément
en mémoire, on déplace alors certains sur disque à un espace réservé à cet effet (swap area ou backing store). Aussi, Un
processus qui est inactif (bloqué) peut être déplacé sur disque (swap out). Le gestionnaire de la mémoire dispose d’une
liste de toutes les zones utilisées et non utilisées de la mémoire. Ainsi, quand un processus requiert de la mémoire pour
son exécution, le gestionnaire trouve un espace libre contigue pouvant le contenir et cet espace lui est attribué (swap in).

Figure 5.5 – Swap

Dans la gestion par partitions variables, l’allocation de la mémoire est dynamique, elle varie en fonction de l’arrivée et
du départ des processus de la mémoire principale. Cependant cette gestion pourrait conduire à l’apparition des trous dans
la mémoire. La conséquence de l’apparition des trous est que la mémoire peut avoir suffisamment d’espace (somme des
espace des trous) pouvant acquellir un processus, mais cependant cet espace libre n’est pas contigue et donc le processus ne
sera pas admis en mémoire. Pour résourdre ce problème, on réunit les espaces inutilisés en une seule partition en déplacant
tous les processus vers le bas : c’est le compactage de la mémoire.

Figure 5.6 – Compactage de la mémoire

Pour que le compactage soit effectif, le gestionnaire se doit de connaître l’état de la mémoire (Quelles sont les espaces
libres ? Quelles sont les esapces occupés ?). Ceci peut être assuré par les techniques de tables de bits (bitmaps), les listes
chaînées et les subdivisions.

5.3.4 Gestion de la mémoire par table de bits


Dans cette technique de gestion, le système d’exploitation utilise une table appelée table de bits pour gérer l’occupation
de la mémoire. La mémoire est divisée en unités d’alloction, et à chaque unité, on fait correspondre un bit dans la table
des bits. Un bit à 1 signifie que l’unité d’allocation y correspondante a été attribuée à un processus et un bit à 0 signifie
que l’unité d’allocation y correspondante est libre.

ICT204 Introduction au système d’exploitation


29/32 CHAPITRE 5. GESTION DE LA MEMOIRE

Plus l’unité d’allocation est faible, plus la table de bits est impotante et en augmentant la taille de l’unité d’allocation,
on réduit la table des bits, mais cependant on augmente le niveau de fragmentation interne. Pour charger un processus de
k unités, il faut trouver k trous consécutifs en mémoire, autrement dit le gestionnaire le gestionnaire de la mémoire doit
parcourir la table à la recherche de k zéros consécutifs.

Figure 5.7 – Mémoire et table de bits

5.3.5 Gestion de la mémoire par liste chaînée


Dans cette technique de gestion, l’occupation de la mémoire est reprrésentée par une liste chaînée de segments, un
segment étant un ensemble d’unités d’allocation consécutives. Chaque noeud de la chaîne est une structure comportant
les élément suivants :
— L’état du segment (libre ou occupé).
— L’adresse de début du segement.
— La longueur du segment.
— Le pointeur sur l’élément suivant de la liste.

Figure 5.8 – Mémoire et liste chaînée

Lorsque la mémoire occupée par un segment est libérée, le gestionnaire fusionne le segment libre avec le ou les segments
adjacents libres s’il y en a. Quatre cas sont envisageables :

Figure 5.9 – Libération de segments

ICT204 Introduction au système d’exploitation


30/32 CHAPITRE 5. GESTION DE LA MEMOIRE

5.3.6 Algorithmes d’allocation de la mémoire


Il existe plusieurs algorithmes d’allocation d’une zone de mémoire libre à un processus. L’objectif est de pouvoir éviter
trop de fragmentation de la mémoire, tout en ayant un algorithme relativement rapide. Les algorithmes très souvent utilisés
pour l’allocation de la mémoire sont les suivants :
— Première zone libre (first fit) : ici, on attribue le premier bloc libre de la liste pouvant contenir le bloc qu’on
désire charger. Cette technique créée beaucoup de fragementation de la mémoire.
— Meilleur ajustement (best fit) : ici, on attribue la plus petite zone libre qui convient au processus qu’on désire
charger. Cette évite de fragmentation des grande zone mémoire.
— Pire ajustement (worst fit) : ici, on attribue la plus grande zone libre au processus qu’on désire charger.
Exemple : Soit un système de mémoire de 1700 KO de mémoire haute (c’est-à-dire au delà de la partie utilisée par
le système d’exploitation) repartie en cinq partitions : 100 KO, 500 KO, 200 KO, 300 KO et 600 KO (dans l’ordre). En
supposant que le système d’exploitation doit allouer des processus de taille 212 KO, 417 KO, 112 KO et 426 KO (dans
l’ordre). Pour chacun des algorithme d’alocation suivants, donner l’allocation obtenue et le taux de fragmentation :
1. First fit.
2. Best fit.
3. Worst fit.
Quel algorithme utilise le plus efficacement la mémoire sur cet exemple ?
NB : le taux de fragmentation est le quotient de la somme de l’espace fragmenté par la somme totale de la mémoire.

5.4 Mémoire virtuelle


Compte tenu du fait qu’un programme pour s’exécuter doit préalablement se trouver en mémoire, il est difficile de
concevoir qu’un programme dont la taille est supérieure à celle de la mémoire puisse s’exécuter. En effet, il existe bien des
programmes dont la taille dépasse celle de la mémoire ! Comment le système d’exploitation s’y prend pour permettre leur
exécution ? Le concept de mémoire virtuelle apporte une solution à ce type de problème et tel est l’objet de cette partie
de notre cours.
Les programmes sont stockés en mémoire virtuelle (espace d’adressage virtuelle ou logique) qui est en réalité une partie
du disque. Il sera donc question pour des programmes tout entier ou des parties des programmes de faire des va-et-vient
entre la mémoire virtuelle et la mémoire physique. Nous verrons les technique de pagination et de segmentation.

5.4.1 Pagination
Dans la technique de pagination :
— L’espace d’adressage d’un processus (espace d’adressage virtuelle) est divisés en unités de taille fixe appelées pages.
— La mémoire physique est découpée en unités d’allocation de taille identique (et égale à celle d’une page) appelées
cadres.
Dan la pagination, nous ne pouvons pas avoir de fragmentation externe (toute les pages on la même taille), mais
cependant une fragmentation interne peut apparaitre, ce qui arrivent si la dernière page de l’espace d’adressage logique
n’est pas pleine.
Chaque processus dispose donc d’une table de page qui lui permettra de faire la correspondance entre les adresses
virtuelles et les adresse physique afin de permettre le chargement des pages en mémoire. Lorsqu’un processus est en cours
d’exécution, seule une partie de son espace d’adressage est en mémoire : c’es la partie résidente (les pages utilisées). Chaque
adresse virtuelle est compsée d’un numéro de page et d’un déplacement dans la page.
Le numéro de page sert d’index dans la table de pages. Il y a autant d’entrées dans la table de pages qu’il y a de pages
dans la mémoire virtuelle. Chaque entrée de la table des pages est une structure comportant :
— Un bit de présence. Ce bit vaut 1 si la page correspondante a déjà été chargée en mémoire et 0 sinon.
— Un bit de référence. Ce bi est positionné chaque fois qu’on accède à la page (en lecture ou en écriure).
— Les bits de modification. Ils permettent de savoir si la page a éé modifiée depuis sa dernière sauvegarde.
— Le numéro de cadre de page. Ce numéro indique dans quelle cadre de la mémoire physique a été chargée la page.
— Les bits de protection.

ICT204 Introduction au système d’exploitation


31/32 CHAPITRE 5. GESTION DE LA MEMOIRE

Conversion d’adresses : Les adresses virtuelles doivent être convertis en adresse physique afin que une page soit
transférée en méoire. Cette convertion est effectuée par le MMU (Memory Management Unit) qui sont des circuits
matériels.

Figure 5.10 – MMU

Quand le processeur veut accéder à une zone mémoire, il passe l’adresse virtuelle au MMU qui la transforme en
adresse physique en se servant de la tale des pages. Deux cas peuvent être envisageable quand le MMU accède à l’entrée
correspondant à la page :
1. La page recherchée se trouve en mémoire. Dans ce cas, il suffit alors d’accéder à l’information recherchée.
2. La page recherchée ne se trouve pas en mémoire. Il se produit alors un déroutement appelé défaut de page. Pour
le traitement des défauts de page :
— S’il y a un cadre de page libre, alors on charge la page virtuelle dans ce cadre.
— S’il n’y a pas de cadre de page libre, alors on utilise un algorithme de remplacement de pages dans un but de
libérer un cadre pour y inclure notre page.

Figure 5.11 – Pagination

Exemple : Pour un programme de 64 Ko (Son espace d’adressage logique est sur le disque) sur une machine 32 Ko
de mémoire, si la taille d’une page est de 4 KO nous avons 16 pages et 8 cadres.

Figure 5.12 – Espace virtuel et espace physique.

ICT204 Introduction au système d’exploitation


32/32 CHAPITRE 5. GESTION DE LA MEMOIRE

Quelques livres Quelques documents utilisés pour la mise sur pied du présent document :
1. Operating systems-with pdf index Modern Operating Systems 2nd Ed by ANDREW S. TANENBAUM.
2. Systèmes d’exploitation, par Hanifa Boucheneb et Juan Manuel Torres-Moreno, Département de génie informatique,
École Polytechnique de Montréal, version 3.90

ICT204 Introduction au système d’exploitation

Vous aimerez peut-être aussi