Vous êtes sur la page 1sur 33

Cours de systèmes

d’exploitation centralisés

Chapitre 5
Les Processus :
Outils de synchronisation
de haut niveau : Les moniteurs

Mr B. SOUICI – Mme L. BOUZAR


© 2018-2019
-1-
1. L’Exclusion Mutuelle
2. Synchronisation des processus avec sémaphores
3. Outils de synchronisation de haut niveau : Les moniteurs

-2-
Les moniteurs
1. INTRODUCTION
2. MONITEURS
2.1 Définition
2.2 Comment assurer l’exclusion mutuelle dans le moniteur ?
2.3 Structure syntaxique d'un moniteur
2.4 Implémentation des moniteurs par sémaphores
2.5 Exemples
2.5.1 Allocateur de ressources
2.5.2 Rendez-vous de n processus
2.5.3 Lecteurs-rédacteurs
2.5.4 Producteurs-consommateurs

-3-
1. INTRODUCTION
• Dans la technique de synchronisation avec sémaphores, un processus
exécute une opération P pour demander l’accès à la ressource, il exécute
une opération V pour la libérer et éventuellement réveiller un processus
en attente de cette ressource.
• L’action de V sur un sémaphore est mémorisée.
• Cette technique ne permet pas le contrôle dès la compilation: Les
variables partagées peuvent être utilisées, en dehors des sections
critiques, sans aucun contrôle.
• Les opérations P et V sont éparpillées dans le programmes ➔ Risque
d’erreur très important : On peut oublier, facilement, un P ou un V.
• D’autres outils de synchronisation existent et permettent d’écrire des
schémas de synchronisation plus clairs, plus structurés et contrôlables à
la compilation. On peut citer :
1) Les moniteurs (Hoare),
2) Les régions critiques conditionnelles (Brinsh Hansen et Hoare).- 4 -
2. MONITEURS
2.1 Définition
• Un moniteur BRINCH HANSEN[73] et HOARE[74] est une entité
syntaxique (module) qui regroupe :
✓ Les variables de synchronisation,
✓ Les ressources partagées,
✓ Les procédures qui manipulent les ressources partagées et les
variables de synchronisation.
• Par définition, les variables déclarées dans le moniteur ne sont
accessibles que par les procédures du moniteur.
• On distingue deux types de procédures du moniteur :
a) Internes : définies pour les besoins internes du moniteur et non
accessibles de l'extérieur.
BRINCH HANSEN[73]: Operating System Principles - Prentice-Hall, 1973.
HOARE[74]: “Monitors: An Operating System Structuring Concept” C.A.R. Hoare CACM,
Volume 17:10, pages 549–557, October 1974. -5-
b) Externes : accessibles de l'extérieur du moniteur, elles constituent
les points d'entrée du moniteur.
• Deux types de synchronisation(contrôle) sont définis dans un moniteur:
1. Exclusion mutuelle :
Réalisée, de manière implicite, entre les procédures du moniteurs ➔
Un seul processus à la fois peut exécuter les procédures du moniteur
jusqu'à ce qu'il sorte du moniteur ou jusqu'à son blocage.
2. Synchronisation :
Réalisée à l’aide de variables de synchronisation et des opérateurs
wait et signal:
✓ Les variables de synchronisation sont définies explicitement avec
l'attribut Condition : On les appelle variables condition.
✓ A chaque variable condition est associée une file d'attente de
processus.
✓ Sur les variables condition on peut appliquer Trois opérateurs :- 6 -
❖ Syntaxe générale

Variable Condition.Opérateur ou Opérateur(Variable condition).

a) Empty : Variable_Condition.empty
C'est une fonction booléenne qui renvoie :
✓ Vrai, si la file de la variable condition est vide(aucun processus
n’est bloqué derrière cette variable condition).
✓ Faux, si la file contient des processus.

b) Wait : Variable_Condition.Wait
Il permet d'exprimer des attentes sur condition en bloquant
systématiquement le processus qui l’exécute ➔
Le processus est inséré dans la file d'attente associée à la variable
condition concernée.

-7-
c) Signal : Variable_Condition.signal;
✓ Il permet de réveiller un processus bloqué dans la file d'attente
de la variable condition concernée.
✓ Si cette file d'attente est vide, le signal n'est pas mémorisé
et son action sera sans effet (pas de mémorisation du
signal).

• Sémantique de l’opérateur Signal


L’opérateur Signal tel qu‘il a été défini risque de provoquer une
violation de l’exclusion mutuelle dans le moniteur:
Deux processus peuvent se retrouver simultanément actifs à
l'intérieur du moniteur:
✓ Le processus qui a exécuté Signal est toujours dans le moniteur.
✓ Le processus réveillé par Signal risque de continuer son exécution
dans le moniteur.
-8-
2.2 Comment assurer l’exclusion mutuelle dans le moniteur ?
• Pour assurer l’exclusion mutuelle entre les procédures du moniteur, la
solution adoptée par HOARE consiste à donner la priorité au
processus réveillé ➔
Le processus exécutant Signal est bloqué jusqu'à ce que le processus
réveillé :
➢ Quitte le moniteur ou
➢ Se bloque à nouveau dans le moniteur ➔
➢ Les processus bloqués suite à une instruction Signal sont plus
prioritaires que les processus en attente(bloqués) sur un point
d’entrée. ➔
➢ Avant d’introduire un nouveau processus bloqué sur un
point d’entrée, vérifier s’il n y a pas de processus bloqués
suite à une instruction Signal.

-9-
1. Files d’attente d’un moniteur :
➢ Une file par moniteur pour assurer l’exclusion mutuelle :
le moniteur est une ressource critique,
➢ N files pour les processus en attente: une file pour chaque variable
condition,
➢ Une file pour les processus bloqués à la suite de l’exécution de
Signal.

Remarque : Si aucune variable condition n’a été déclarée ➔


- Zéro file (n=0) pour les processus en attente et
- Zéro file pour les processus bloqués à la suite d’un signal
(il n y aura aucun signal).

- 10 -
2. Représentation schématique des files d’attente du moniteur

- 11 -
2.3 Structure syntaxique d'un moniteur (1)
Nom : Moniteur;
✓ Déclaration des variables partagées;
✓ Déclaration des variables Condition;
✓ Déclaration des procédures externes:
Procédure Nom Entry(paramètres éventuels);

✓ Déclaration des procédures internes:


Procédure Nom(paramètres éventuels);
Début
✓ Initialisation des variables;
Fin du moniteur.
❖ Appel d’une procédure du moniteur (ou point d’entrée du moniteur)

Nom_du_moniteur.Nom _procédure_externe(paramètres);
- 12 -
2.3 Structure syntaxique d'un moniteur (2)
Nom : Moniteur;
✓ Déclaration des variables partagées;
✓ Déclaration des variables Condition;
✓ Déclaration des procédures externes;
Externe Nom1, Nom2, …, Nomn;
Procédure Nomi (paramètres éventuels);
✓ Déclaration des procédures internes;
Procédure Nom(paramètres éventuels);
Début
✓ Initialisation des variables;
Fin du moniteur.
Appel d’une procédure du moniteur (ou point d’entrée du moniteur).
Nom_du_moniteur.Nom _procédure_externe(paramètres);
- 13 -
2.4 Implémentation des moniteurs par sémaphores
• Signal peut apparaître n'importe où dans une procédure du moniteur.
• Le processus exécutant Signal doit se bloquer temporairement au profit
du processus qu'il a réveillé.
1) Exclusion mutuelle implicite
✓ Un seul sémaphore d‘exclusion mutuelle commun à toutes les procédures
externes suffit:
Sémaphore Mutex_nom_du_moniteur init 1;
✓ Un sémaphore Urgent derrière lequel seront bloqués les processus
exécutant une opération Signal.
Sémaphore Urgent init 0;
✓ Un compteur Urgent_count : permet de compter le nombre de processus
bloqués dans la file du sémaphore Urgent.
Entier Urgent_count init 0;
- 14 -
Traduction :
Toute procédure externe aura donc la forme suivante:

- 15 -
Procedure nom_proc(paramètres) Procedure nom_proc(paramètres)
Début Begin
Entrée de la procédure; P(Mutex_nom du moniteur);
Corps de la procédure; Corps de la procédure;
Begin
If (Urgent_count > 0) then
/* Réveiller un processus
bloqué à la suite de l’exécution
de Signal et quitter sans
Sortie de la procédure; libérer la SC */
V(Urgent);
Else
V(Mutex_nom_du_moniteur);
End;
Fin; End; - 16 -
2) Attentes
1. Attente sur une variable condition : Cond.wait
Associer à chaque variable condition :
• Un sémaphore de synchronisation cond_sem initialisé à 0;
Sémaphore cond_sem init 0;
• Un compteur de processus bloqués dans la file cond_count
initialisé à 0.
Entier cond_count init (0);
2. Attente temporaire des processus exécutant Cond.Signal :
Le processus exécutant Cond.Signal est bloqué jusqu’à ce que le
processus libéré quitte le moniteur ou se bloque à nouveau.
On utilise le sémaphore Urgent et le compteur Urgent_count définis
précédemment .

- 17 -
Cond.Wait Cond.signal;
Begin Begin

Cond_count := Cond_count + 1; If(Cond_count > 0) then

If (Urgent_count > 0) then Begin /* il y a des processus en


/* Réveiller un processus attente */
bloqué à la suite de Urgent_count := Urgent_count + 1;
l’exécution de Signal et
V(Cond_sem);
quitter sans libérer
la Section Critique */ /* le processus qui a exécuté signal
se met en attente(se bloque) */
V(Urgent);
P(Urgent);
Else V(Mutex_nom du moniteur);
Urgent_count := Urgent_count - 1;
P(Cond_sem);
End;
Cond_count := Cond_count - 1;
End;
End;
- 18 -
❖ Remarques :
L'interblocage entre processus exécutant des moniteurs différents est
possible:
• Une procédure d'un moniteur MA peut appeler une procédure d'un
autre moniteur MB pour le même processus : ➔
les 2 moniteurs restent verrouillés pendant cette exécution.
• Le moniteur MA comporte les procédures P1, P2,... , Pn.
• Le moniteur MB comporte les procédures L1, L2,... , Lm.
• Les appels croisés tels que:
MA.Pi appelle MB.Lj et
MB.Lj appelle MA.Pk ➔ Interblocage
Chaque moniteur ayant besoin des services de l'autre restera verrouillé
pendant toute l’exécution de ces appels croisés.

- 19 -
2.5 Exemples

2.5.1 Allocateur de ressources

a) Allocation d'une ressource critique (ex : une imprimante)

Processus i
Début
Ressource.Allouer;
Utiliser la ressource;
Ressource.Libérer;
Fin du processus i;

- 20 -
Ressource : moniteur;
occupée : booléen; /* faux : ressource libre;
vrai : ressource occupée. */
Roccupée : condition; /* variable condition */
Externe Allouer, Libérer; /* procédures externes */

Procedure Allouer; Procedure Libérer;


Début Début
Si occupée alors Roccupée.Wait; occupée := Faux;
occupée := Vrai; Roccupée.Signal;
Fin Allouer; Fin Libérer;

/* Initialisation */
Début
occupée := Faux;
Fin Ressource. - 21 -
b) Nombre de ressources est égal à n (ex : n imprimantes)

Processus i
Début
Ressource.Allouer;
Utiliser la ressource;
Ressource.Libérer;
Fin du processus i;

- 22 -
Ressource : moniteur;
nlibre : entier; /* nlibre : nombre de ressources libres;
attendre : condition; /* variable condition */
Externe Allouer, Libérer; /* procédures externes */

Procedure Allouer; Procedure Libérer;


Début Début
nlibre := nlibre -1; nlibre := nlibre +1;
Si nlibre<0 alors attendre.Wait; attendre.Signal;
Fin Allouer; Fin Libérer;
Procedure Allouer;
Début
Si nlibre=0 alors attendre.Wait;
nlibre := nlibre -1;
Fin Allouer;
/* Initialisation */
Début nlibre:= n;
Fin Ressource. - 23 -
Ressource : moniteur;
nlibre : entier; /* nlibre : nombre de ressources libres;
attendre : condition; /* variable condition */
Externe Allouer, Libérer; /* procédures externes */

Procedure Allouer; Procedure Libérer;


Début Début
nlibre := nlibre -1; nlibre := nlibre +1;
Si nlibre<0 alors attendre.Wait; attendre.Signal;
Fin Allouer; Fin Libérer;
Procedure Allouer;
Début
Si nlibre=0 alors attendre.Wait;
nlibre := nlibre -1;
Fin Allouer;
/* Initialisation */
Début nlibre:= n;
Fin Ressource. - 24 -
2.5.2 Rendez-vous de N processus

Processus i

Rendez-vous.Arriver; /* point de rendez-vous */

Fin processus i

- 25 -
Rendez-vous : moniteur;
entier cpt ; /* nbre de processus arrivés au point de
rendez-vous*/
Rdv : condition; /* variable condition */
externe Arriver;
Procedure Arriver;
Début
cpt := (cpt+1) mod N;
Si cpt  0 alors Rdv.wait;
Rdv.signal; /* réveil en cascade */
Fin Arriver;
Début
cpt := 0;
Fin Rendez-vous.
- 26 -
2.5.3 Problème des Lecteurs-Rédacteurs

Processusi
/* Lecture du fichier f */
Lecteur_Rédacteur.Demande_lecture
< Lire>
Lecteur_Rédacteur.fin_lecture

/* Ecriture du fichier f */
Lecteur_Rédacteur.Demande_ecriture
< Ecrire>
Lecteur_Rédacteur.fin_ecriture

- 27 -
a1) Ordre d’accès au fichier f quelconque
Lect_Rédacteur : moniteur;
ecrit : booléen ; nl : entier; clect, cecr: condition;
externe Demande_Lecture, Fin_Lecture,Demande_ecriture, Fin_écriture;
Procédure Demande_Lecture Procédure Demande_ecriture
Début Début
Si ecrit alors clect.wait; Si ecrit ou (nl>0) alors cecr.wait;
nl := nl + 1; ecrit := vrai ;
clect.signal; /* réveil en cascade*/ Fin;
Sinon nl:=nl+1; Finsi
Fin;
Procédure Fin_lecture Procédure Fin_ecriture
Début Début
nl:= nl-1; ecrit:=faux;
Si nl=0 alors cecr.signal; Si cecr.empty alors
Fin; clect.signal;
Sinon
cecr.signal ;
Fin;

Début ecrit := faux ; nl := 0;


Fin lecteur_rédacteur. - 28 -
a2) Ordre d’accès au fichier f quelconque
Lecteur_Rédacteur : moniteur ;
ecrit : booléen ; nl : entier ; cf, cecr : condition ;
Externe Demande_lecture , Fin_lecture, Demande_ecriture, Fin_ecriture;
Procédure Demande_lecture Procédure Demande_ecriture
Début Début
Si ecrit alors cf.wait; Si ecrit ou (nl > 0) alors cf.wait;
nl := nl + 1; Si ecrit ou (nl > 0) alors
cf.signal; /* réveil en cascade début cf.signal; cecr.wait; fin;
de processus lect ou red */ Finsi;
Sinon nl:=nl+1; Finsi ecrit := vrai ;
Fin; Fin;
Procédure Fin_lecture Procédure Fin_ecriture
Début Début
nl := nl-1; ecrit := faux;
Si nl = 0 alors Si non(cecr.empty) Si non(cecr.empty) Alors
Alors cecr.signal; cecr.signal;
Sinon cf.signal; Sinon
finsi cf.signal ;
Fin; Fin;
Début ecrit := faux ; nl := 0 ;
Fin lecteur_rédacteur. - 29 -
b1) Ordre d’accès au fichier f selon FIFO
Lecteur_Rédacteur : moniteur;
ecrit : booléen ; nl : entier; cecr, Fifo : condition;
Externe Demande_lecture , Fin_lecture, Demande_ecriture, Fin_ecriture;
Procédure Demande_lecture Procédure Demande_ecriture
Début Début
Si(non(Fifo.empty) ou ecrit) alors Si ecrit ou (nl > 0 ) alors Fifo.wait;
Fifo.wait; Ecrit := vrai; /* écriture ou
nl := nl + 1; attente d’écriture*/
Fifo.signal; /* réveil en cascade*/ Si nl > 0 alors cecr.wait;
Fin; Sinon
Ecrit := vrai; /* écriture*/
Finsi;
Fin;
Procédure Fin_lecture Procédure Fin_ecriture
Début Début
nl := nl-1; ecrit := faux;
Si nl = 0 alors Si non(cecr.empty) Fifo.signal ;
Alors cecr.signal; Fin;
Sinon Fifo.signal;
Finsi;
Fin;
Début ecrit := faux ; nl := 0 ;
Fin lecteur_rédacteur. - 30 -
b2) Ordre d’accès au fichier f selon FIFO
Lecteur_Rédacteur : moniteur;
ecrit : booléen ; nl: entier ; cecr,Fifo : condition ;
Externe Demande_lecture , Fin_lecture, Demande_ecriture, Fin_ecriture;
Procédure Demande_lecture Procédure Demande_ecriture
Début Début
Si(non(Fifo.empty) ou Si(non(Fifo.empty) ou (nl>0) ou
non(cecr.empty) ou ecrit) alors non(cecr.empty) ou ecrit)) alors
Fifo.wait; Fifo.wait;
nl := nl + 1; Si nl>0 alors cecr.wait;
Fifo.signal; /* réveil en cascade*/ Finsi;
Fin; ecrit := vrai ; /* ecrire */
Fin;
Procédure Fin_lecture Procédure Fin_ecriture
Début Début
nl := nl-1; ecrit := faux;
Si nl = 0 alors Fifo.signal;
Si non(cecr.empty) cecr.signal; Fin;
Sinon Fifo.signal;
Fin;
Début ecrit := faux ; nl := 0;
Fin lecteur_rédacteur. - 31 -
2.5.4 Modèle des producteurs-consommateurs

Programmes des producteurs et des consommateurs

Producteur Consommateur
Mp : message; Mc : message;
Début Début
Répéter Répéter
Produire(Mp); Prod_Cons.demande_retrait(Mc);
Prod_Cons.demande_dépot(Mp); Consommer(Mc);
Jusqu’à faux; Jusqu’à faux;
Fin; Fin;

- 32 -
Prod_Cons: moniteur ;
Plein entier; in, out : entier; Tampon : tableau[0..n-1] de message;
Nvide,Nplein : condition;
Externe demande_dépot, demande_retrait;

Procédure demande_dépot(Mp) Procédure demande_retrait(Mc)


Début Début
Si plein = n alors nplein.wait; Si plein = 0 alors Nvide.wait;
;
Déposer(Mp); Retirer(Mc);
Plein := plein + 1: Plein := plein - 1;
Nvide.signal; /* signaler depôt*/ Nplein.Signal; /* signaler retrait*/
Fin; Fin;

Procédure déposer(Mp) Procédure Retier(Mc)


Début Début
Tampon[in] := Mp; Mc := Tampon[out];
In := (in +1) mod n; out := (out+1) mod n;
Fin; Fin;
Début
Plein := 0; in := 0; out := 0; Procédures
Fin Pro_Cons. internes
- 33 -

Vous aimerez peut-être aussi