Institut Supérieur d Informatique Chapitre 02 Synchronisation des processus Dr. Mohamed-Wassim YOUSSEF 2009 [www.wassimyoussef.info] Systèmes d exploitation avancées 1 ING ISI 1 ére année Ingénieur en Informatique Synchronisation des processus Systèmes d exploitation Avancées 1. Autres utilisations des sémaphores 2. Pb des Lecteurs/rédacteur 2 1
Réfléchissons! 3 Soient les deux processus P1 et P2 suivants. Ils se partagent deux sémaphores S1 et S2 initialisés à 0. Semaphore S1 0 Semaphore S2 0 P1 { procedure A1 ; Up(S2) ; Down(S1) ; procedure B1 ; P2 { procedure A2 ; Up(S1) ; Down(S2) ; procedure B2 ; Quelle synchronisation a t on imposée sur les exécutions des procédures A1, A2, B1 et B2 (càd, quel ordre d exécution)? Barrière de synchronisation Les Ai s exécutent toujours avant les Bi, quelque soit l ordre de l exécution des processus P1 et P2 4 Semaphore S1 0 Semaphore S2 0 P1 { procedure A1 ; Up(S2) ; Down(S1) ; procedure B1 ; P2 { procedure A2 ; Up(S1) ; Down(S2) ; procedure B2 ; Ex: Ecrire le code à fin d imposer la même synchronisation pour N processus en utilisant : N sémaphores 2sémaphores et un compteur 2
Lecteurs/rédacteur 5 Une base de données peut être accessible par un seul rédacteur ou N lecteurs en même temps Exclusion mutuelle entre le rédacteur et les N lecteurs Donner le pseudo code d un processus lecteur et celui du processus rédacteur Base de données Lecteurs/Rédacteur 6 Semaphore mutex 1 Semaphore db 1 int nb_lect = 0 ; //lecteur void lecture(){ while (true) { // contrôle l accés à nb_lect // contrôle l accés à la base de données // var partagées entre lecteurs pour // compter le nombre de lecteurs accédant // actuellement à la BD //boucle sans fin down (mutex); // la modif de la var. partagée nb_lect est une nb_lect ++; // section critique entre lecteurs if (nb_lect == 1) down (db); //si le premier lecteur up(mutex); // libère l accés exclusif à nb_lect lire_la_bd(); _ //accés à la BD down(mutex); nb_lect --; if (nb_lect == 0) up (db); //si le dernier lecteur up (mutex) utiliser_données (); //Section restante 3
Lecteurs/Rédacteur 7 Semaphore mutex 1 Semaphore db 1 int nb_lect = 0 ; //redacteur void ecriture(){ while (true) { // contrôle l accés à nb_lect // contrôle l accés à la base de données // var partagées entre lecteurs pour // compter le nombre de lecteurs accédant // actuellement à la BD //boucle sans fin créer_données (); //Section restante down (db); ecrire_dans_la_bd(); up (db); //accés à la BD Moniteurs 8 Mini rapport individuel de deux pages max Fichier pdf à envoyer avant MARDI 24/11/09 à wyoussef_isi@yahoo.fr 4
Les Moniteurs 9 Un moniteur est un module de programme de haut niveau permettant au compilateur (pas au processus utilisateur) de réaliser l exclusion lexclusion mutuelle. Un moniteur est constitué d'un ensemble de variables d'état et de procédures possédant les caractéristiques suivantes : 1. Seules certaines procédures, appelées entrées (entry) du moniteur peuvent être appelées de l'extérieur 2. Un seul processus actif dans un moniteur à un moment donné. 3. Les variables d'état ne sont pas visibles de l'extérieur du module 4. Le moniteur fournit des possibilités de synchronisation au moyen de conditions. 5. Une instruction initiale est exécutée une seule fois à l'initialisation du programme Les Moniteurs 10 Une condition C est une variable manipulable par seulement deux opérations : L'opération Lopération attendre(c) (en anglais wait(c)): bloque le processus appelant et le place en queue de file d'attente L'opération signaler(c) (en anglais signal(c)): retire un processus en tête de la file d'attente, si elle est non vide, et l'active. Une condition est implantée dans un système d exploitation comme une file d'attente de processus bloqués, c'est à dire une structure de données capable de mémoriser le blocage de processus. En général, une condition de synchronisation est exprimée à l'aide d'une expression booléenne faisant intervenir les valeurs des variables d'état : SI NON <condition> ALORS attendre (c) FSI; 5
Les Moniteurs 11 Moniteur ressource ; var ressource_libre : booleen; libre : condition; Procédure acquérir () si non ressource_libre alors attendre(libre) fsi; ressource_libre:= Faux; fin acquérir; Procédure libérer () ressource_libre := vrai; signaler(libre); fin liberer; ressource_libre := vrai; fin ressource; Les Moniteurs 12 Moniteur ressource ; Nom du moniteur var ressource_libre : booleen; libre : condition; Procédure acquérir () Variables et conditions globales portant sur les ressources partagées si non ressource_libre alors attendre(libre) fsi; ressource_libre:= Faux; fin acquérir; Procédure d entrée en section critique Procédure libérer () ressource_libre := vrai; signaler(libre); fin liberer; ressource_libre := vrai; fin ressource; Procédure quitter section critique Fonction principale d initialisation du moniteur 6
monitor ProdConso condition full, empty; integer count; procedure insert (item) begin if count = N then wait(full) insert_item(item); count++; if (count = 1) then signal(empty); end; procedure remove () begin if count = 0 then wait(empty); item = remove_item; count--; if (count = N 1) then signal(full); end; count = 0; end monitor; procedure producteur begin while true { item = produce_item; ProdConso.insert(item); end; 13 procedure consommateur begin while true { item = ProdConso.remove; consume_item(item); end; 14 7
Implémentation en Java (1/3) public class MoniteurProdCons { String tampon; boolean est_vide = true; synchronized void prod(string m){ if (!est_vide){ System.out.println("Producteur attend"); try { wait(); catch (InterruptedException e){ System.out.println("Produit: "+m); tampon = m; est_vide = false; notify(); synchronized void cons(){ if (est_vide){ System.out.println("Consommateur attend"); try{ wait(); catch (InterruptedException e){ System.out.println("Consomme: "+tampon); est_vide = true; notify(); Implémentation en Java (2/3) 16 public class Producteur extends Thread{ MoniteurProdCons tampon; public Producteur (MoniteurProdCons t){ tampon = t; public void run(){ tampon.prod("message1"); tampon.prod("message2"); try{ sleep(100); catch (InterruptedException e){ tampon.prod("message3"); public class Consommateur extends Thread{ MoniteurProdCons tampon; public Consommateur (MoniteurProdCons t){ tampon = t; public void run(){ tampon.cons(); tampon.cons(); tampon.cons(); 8
Implémentation en Java (3/3) 17 public class ProdConsTest { public static void main(string argv[]){ MoniteurProdCons tampon = new MoniteurProdCons(); new Producteur(tampon).start(); new Consommateur(tampon).start(); Implémentation en C avec les pthread (1/3) #include <pthread.h> #include <string.h> static pthread_cond_t est_libre, est_plein; static pthread_mutex_t t protect; static char *buffer; /* Depose le message msg (qui est dupliqué). Bloque tant que le tampon est plein. */ void deposer (char *msg) { pthread_mutex_lock (&protect); while (buffer!= NULL) pthread_cond_wait (&est_libre, &protect); /* buffer = NULL */ buffer = strdup (msg); /* duplication de msg */ pthread_cond_signal (&est_plein); pthread_mutex_unlock (&protect); 9
Implémentation en C avec les pthread (2/3) /* Renvoie le message en tête du tampon. Bloque tant que le tampon est vide. * La libération de la mémoire contenant le message est à la charge de l'appelant. l */ char * retirer (void){ char *result; pthread_mutex_lock (&protect); while (buffer == NULL) pthread_cond_wait (&est_plein, &protect); /* buffer!= NULL */ result = buffer; buffer = NULL; pthread_cond_signal (&est_libre); pthread_mutex_unlock (&protect); return result; Implémentation en C avec les pthread (3/3) 20 /* Initialise le producteur/consommateur. */ void init_prodco (void) { pthread_mutex_init (&protect, NULL); pthread_cond_init (&est_libre, NULL); pthread_cond_init (&est_plein, NULL); buffer = NULL; 10