Process Synchronisation



Comments



Description

Chapitre 4.4. Processus et sémaphores 4.1. Introduction Dans un système d’exploitation, il y a de nombreux processus concurrents qui désirent accéder aux ressources de l’ordinateur (UC, mémoire, fichiers, périphériques). Si la ressource n’est pas disponible, il faut bloquer le processus jusqu’à ce qu’elle le soit. On définit : Processus actif Processus prêt Processus bloqué Il s’exécute en UC Il a toutes ses ressources sauf l’UC Il lui manque une (ou plusieurs) ressource pour continuer son exécution Ressource critique Un seul processus peut y accéder Exclusion mutuelle 2 processus voulant accéder à une ressource critique sont en exclusion mutuelle : l’un ou l’autre, mais pas les deux 4.2. Exclusion mutuelle et sémaphores 4.2.1. Définitions Un sémaphore est une variable accessible seulement à l’aide des opérations P (Proberen : tester) et V (Verhogen : incrémenter) suivantes : P(S) Puis-je ? S= S–1; si S < 0 alors Le processus réalisant P(S) est bloqué dans une file d’attente spécifique de chaque sémaphore V(S) vas-y S= S+1 si S >= 0 alors un des processus de la file d’attente est débloqué Seul P peut bloquer un processus, V n’est jamais bloquant. 4.2.2. Réalisation d’opérations P et V avec des tubes On peut réaliser les opérations P et V à l’aide d’un tube Unix contenant des jetons. Un jeton est représenté par un caractère quelconque. Le sémaphore est initialisé avec un certain Prof. C.EL AMRANI Programmation système sous UNIX 2 Chapitre 6. Processus et sémaphores nombre de jetons. Une opération P consiste à prendre un jeton (ici lire un caractère du tube read), si le tube est vide, le processus est bloqué en attente d’un jeton. Une opération V consiste à ajouter un jeton (ici écrire un caractère dans le tube write). Ainsi on définit pour les exemples suivants : fonction Initsem fonction P fonction V type Semaphore crée un sémaphore et l’initialise avec N jetons (N caractères ‘a’) lit un caractère ‘a’ du tube ou bloque le processus faisant P si le tube est vide (read est bloquant) écrit un caractère ‘a’ dans le tube correspond au double descripteur d’un tube anonyme tubesem.h est l’en-tête du module sur les sémaphores : (à sauver dans /usr/include) #include<unistd.h> /* read, write */ #include<sys/types.h> /* pid_t */ #include<sys/wait.h> /* wait */ typedef int Semaphore [2] ; void Initsem(Semaphore S, int N); void P(Semaphore S); void V(Semaphore S); void attente(int N); void message(int i, char* s); tubesem.c est le corps du module sur les sémaphores, constitué de sémaphores avec tubes anonymes P et V : #include<stdio.h> #include<stdlib.h> #include"tubesem.h" /* initialiser le semaphore S */ void Initsem(Semaphore S, int N) { int i ; char c='a'; pipe(S); for(i=1;i<=N;i++)write(S[1],&c,1); } /* P sur le semaphore S, prendre un jeton 'a' */ void P (Semaphore S) { char c; read(S[0],&c,1); } /* V sur le semaphore S, remettre un jeton 'a' */ void V (Semaphore S) Prof. C.EL AMRANI Programmation système sous UNIX 3 Chapitre 6. Processus et sémaphores { char c='a'; write(S[1],&c,1); } /* Attendre un nombre aleatoire de secondes entre 0 et N-1*/ void attente(int N) { sleep(rand() % N); } /* Ecrire un message s dans la i eme colonne, la premiere colonne a le numero 1 */ void message(int i, char* s) { #define colonne 20 int Nb, j ; Nb=(i-1)*colonne; for(j=0; j<Nb; j++) putchar(' '); printf("%s\n" ,s); fflush(stdout); } Le problème de l’accès en exclusion mutuelle à une variable partagée peut être résolu en initialisant un sémaphore à 1 (un jeton est disponible) La section critique est encadrée par P et V. Si le jeton est disponible, le processus entre dans la section critique. Si le jeton est pris par un autre processus, le processus faisant P est bloqué jusqu’à ce que le jeton soit remis par le processus l’utilisant lors de la sortie de sa section critique. S : Sémaphore initialisé à 1 N : variable commune aux deux processus p1 et p2 processus p1 … P(S) ; N=N+1; V(S) ; … processus p2 … P(S) ; N=N+1; V(S) ; … La variable N ne peut être modifié que par un seul processus à la fois (p1 ou p2). 4.2.3. Exemple du carrefour routier On peut simuler la procédure que doit suivre une voiture à un carrefour routier : s’engager dans le carrefour si aucune voiture n’y est engagée, sinon attendre que le carrefour soit libre. Il y a donc exclusion mutuelle pour la traversée du carrefour. Prof. C.EL AMRANI Programmation système sous UNIX 4 Chapitre 6. Processus et sémaphores Exclusion mutuelle dans un carrefour La simulation du carrefour routier peut se faire en utilisant le module « tubesem.h », et en créant des processus « voiture » à l’aide de l’appel système fork (). La fonction voiture () a pour effet de créer un nouveau processus à chaque appel. tubesem.c #include<stdio.h> #include<stdlib.h> #include"tubesem.h" Semaphore C; main() { int i ; void voiture(int,int); printf("\n%20s%20s%20s\n","VOITURE 1","VOITURE 2","VOITURE 3"); Initsem(C,1); voiture(1,3); voiture(2,1); voiture(3,3); for(i=1;i<=3;i++)wait(0); } /* inclure ici les définitions des fonctions: Initsem, P, V, attente et message données plus haut */ void voiture(int n,int duree) { if(fork()==0) { attente(duree); message(n,"Arrivee"); Prof. C.EL AMRANI Programmation système sous UNIX 5 Chapitre 6. Processus et sémaphores P(C); message(n,"Traversee"); attente(duree); message(n,"Depart"); V(C); exit(0); } } Résultat : ./tubesem VOITURE 1 VOITURE 2 Arrivee Traversee Depart VOITURE 3 Arrivee Traversee Arrivee Depart Traversee Depart ./tubesem VOITURE 1 Arrivee Traversee Depart Traversee Arrivee Depart Traversee Depart Remarque : Si on veut autoriser la traversée du carrefour par deux voitures simultanément, il faut initialiser le sémaphore C à 2 (il contient 2 jetons). Exemple : ./tubesem (avec C initialisé à 2) VOITURE 1 VOITURE 2 VOITURE 3 Arrivee Traversee Arrivee Traversee Depart Arrivee Traversee Depart Depart Prof. C.EL AMRANI Programmation système sous UNIX VOITURE 2 VOITURE 3 Arrivee 6 Chapitre 6. Processus et sémaphores 4.3.3. Exemple du producteur-consommateur Un exemple courant de synchronisation entre processus concerne la communication de données dans une zone de mémoire partagée. Un même zone de mémoire est accessible par deux processus, l’un fournit les valeurs (processus producteur), et l’autre les utilise (processus consommateur). Les deux processus doivent se synchroniser. Le consommateur ne peut pas exploiter la valeur si celle-ci n’est pas disponible. Le producteur ne doit pas produire une nouvelle valeur si la précédente n’a pas été exploitée. Ainsi pour une zone mémoire commune à une place : message S1 S2 Variable commune aux 2 processus Sémaphore initialisé à 1 Sémaphore initialisé à 0 processus consommateur … Puis-je consommer ? P(S2) processus producteur … Puis-je produire P(S1) ; Déposer les données dans message ; Consommer les données dans message ; Vas-y consommes V(S2) ; … Vas-y produis P(S1) ; … Le consommateur attend le producteur. Le producteur attend que le message soit consommé avant de produire un nouveau message. Il y a bien synchronisation des deux processus. Pour une zone commune à N places, il suffit d’initialiser le sémaphore S1 à N (l’initialisation de S2 est maintenue à 0). La zone est une réserve de N éléments, le producteur est chargé de la remplir ; il est bloqué si la réserve est pleine. Le consommateur prend les éléments dans la réserve ; il est bloqué si la réserve est vide. 4.4. Interblocage (deadlock) Certaines synchronisation peuvent conduire à un interblocage des processus lorsqu’un processus attend des ressources utilisées par un autre processus et vice versa. Soient les processus p1 et p2 tel que : p1 possède la Ressource 1 Ressource1 p2 attend la Ressource1 S1 S2 Sémaphore initialisé à 1 Sémaphore initialisé à 1 Programmation système sous UNIX p2 p1 p1 attend la Ressource 2 Ressource2 p2 possède la Ressource2 Prof. C.EL AMRANI 7 Chapitre 6. Processus et sémaphores processus p1 … P(S1) ; (A) P(S2) ; … V(S2) ; V(S1) ; … processus p2 … P(S2) ; (B) P(S1) ; … V(S1) ; V(S2) ; … p1 possède Ressource1 et attend Ressource2. p2 possède Ressource2 et attend Ressource1. Dans ce cas les deux processus sont éternellement bloquées. p1 est bloqué sur S2 et est interrompu en (A). p2 est bloqué sur S1 et est interrompu en (B). Chaque processus attend que l’autre libère la ressource dont il a besoin. On peut éviter les problèmes d’interblocage en imposant un ordre dans l’attribution des ressources. Sur l’exemple ci-dessus, l’ordre d’abord S1, puis ensuite S2 pour tous les processus, ne peut conduire à un interblocage. Prof. C.EL AMRANI Programmation système sous UNIX
Copyright © 2024 DOKUMEN.SITE Inc.