Vous êtes sur la page 1sur 48

Ingénierie des Systèmes d’Exploitation

Chapitre 4 : Communication Interprocessus &


Synchronisation

Pr HANIN

2022/2023
Plan

 Chapitre 1 : Processus (Introduction générale)

 Chapitre 2 : Création / Manipulation des processus

 Chapitre 3: Ordonnancement des processus

 Chapitre 4 : Communication entre processus & Synchronisation

 Chapitre 5: Gestion de la mémoire

 Chapitre 6: Gestion des entrées sorties et des fichiers

Cours: Ingénierie Systèmes d’exploitation Chapitre 4 : Communication interprocessus & Synchronisation 2


PLAN (Chapitre 4)

o Communication interprocessus

o Signaux

o Tubes/ pipes

o Synchronisation

o Terminologie : Thread, ressource partagée, exclusion


mutuelle, section critique..

o Critères de bonne synchronisation des processus

o Méthodes d’Attente active

o Méthodes d’Attente passive

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 3


Signaux

 Les signaux représentent un mécanisme asynchrone de communication interprocessus.

 Les signaux sont asynchrones, c.-à-d. que le processus auquel un signal est délivré ne
peut pas déterminer à l’avance le moment où il recevra le signal.

 Les signaux sont envoyés à un ou plusieurs processus.

 Le processus visé reçoit le signal sous forme d’un drapeau dans son bloc de contrôle.

 Chaque signal a un nom symbolique. Sous Unix, la liste des signaux est définie dans
<signal.h>. Cette liste peut être affichée à l’aide de la commande Unix: Kill -l

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 4


Communication par signaux

Principaux signaux

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 5


Communication par signaux

Signaux

Pr.HANIN Chapitre 4: Communication interprocessus & Synchronisation 6


Communication par signaux

Signaux: Primitive kill()

 Un signal est envoyé à un processus en utilisant l’appel système:

int kill( int pid, int signal )

o Signal est un numéro compris entre 1 et NSIG (défini dans <signal.h>).

o Pid est le numéro du processus auquel le signal est envoyé.


 pid positif : le processus du pid indiqué

 pid négatif : tous les processus du groupe pid

 0 : tous les processus du groupe du processus réalisant l’appel kill

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 7


Communication par signaux

Exemple : kill()

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

Envoie le signal sig au processus de PID pid.

Retour:

• 0 si OK

• -1 en cas d'erreur
UCP

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 8


Tubes

 Les signaux constituent un moyen de communication entre processus. Mais ils ne


permettent pas d'échanger des données. Pour réaliser de tels échanges, il faut utiliser des
tubes de communication (i.e. fichiers).

 Un tube est un moyen de transmission de données d'un processus à un autre.

 Il existe deux types de tubes :

 Anonymes : Pour mettre en relation des processus d’un même groupe (ses ancêtres et ses
descendants).

 Nommés : Pour mettre en relation n'importe quels processus.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 9


Tubes anonymes en C (Unix): Création

 La création d’un tube est réalisée par la primitive pipe.

#include <unistd.h>

int pipe(int p[2]);

 La valeur de retour de pipe() est 0 en cas de succès, -1 sinon (trop de descripteurs actifs,
ou de fichiers ouverts, etc...)

 Elle correspond à la création de deux descripteurs de fichiers, l’un permettant d’écrire


dans le tube et l’autre d’y lire, par les opérations de lecture/écriture classiques
(read/write par exemple).

 Un fils hérite des tubes créés par le père et de leurs descripteurs.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 10


Tubes anonymes

 La communication est unidirectionnelle.

 La communication est faite en mode FIFO (First In First Out). Premier écrit, premier
lu.

 Ce qui est lu quitte définitivement le tube et ne peut être relu.

 La transmission est faite en mode flot continu d'octets. L'envoi consécutif des deux
séquences "abcd" et "efg" est semblable à "abcdefg" et peut-être lu en totalité ou en
morceaux comme "ab", "cde" et "fg" par exemple.

 Pour fonctionner, un tube doit avoir au moins un lecteur et un écrivain . Il peut y en avoir
plusieurs.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 11


Tubes Anonymes: les primitives close/read/write

int read(int desc, void* pt, size_t taille);

permet de lire les données se trouvant dans le tube dont le descripteur est desc et écrit ces
données à l'emplacement mémoire pt. Par défaut, cette primitive est bloquante tant que les
données à lire ne sont pas disponibles sur le descripteur.

int write(int desc, void* pt, size_t taille);

permet d’écrire les données se trouvant à l'emplacement mémoire pt, dans le tube
correspondant au descripteur d’écriture desc.

int close(int desc);

ferme un descripteur et libère les ressources associées. L'utilisation du close() indiquera


également que l'on ne souhaite plus écrire dans le tube.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 12


Tubes Anonymes
 On peut écrire dans un tube avec la primitive classique write(). L'écriture est faite en
utilisant le descripteur p[1].

 La séquence qui suit:

int p[2];

pipe(p);
.........................
char txt[100]="texte a écrire ";

close p[0];
write(p[1], txt, 20);

est une demande d'écriture de 20 caractères (octects) dans le tube de descripteur ouvert
p[1]. La séquence à écrire est prise dans la zone txt. La valeur de retour de write() est le
nombre d'octets ainsi écrits. Une précaution voudrait qu'un processus ferme
systématiquement les descripteurs dont il n'a pas besoin.
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 13
Tubes Anonymes

 On peut lire dans un tube à l'aide de la primitive classique read(). On utilise le


descripteur p[0] rendu par pipe(). Dans l'exemple qui suit:

int p[2];

pipe(p);
................;
char txt[100];

close(P[1]);

read(p[0], txt, 20);

on a une demande de lecture de 20 caractères dans le tube p. Les caractères lus sont
stockées dans la zone txt. Le nombre de caractères lus est la valeur de retour de read().
Une précaution voudrait qu'un processus ferme systématiquement les descripteurs dont il
n'a pas besoin.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 14


Tubes Anonymes: Exemple 1

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 15


Tubes Anonymes: Exemple 2
 Le père envoie au fils un message dans un tube. Le message est envoyé en bloc et lu
caractère par caractère puis imprimé.

#include <stdio.h> else { /* suite pere */

#include <unistd.h> char message[25] = "Cela provient d'un tube";

close(p[0]);

main() { /* communication PERE --> FILS par pipe */ write(p[1], message, 24);

int p[2]; close(p[1]);

if (pipe(p) == -1) { printf("erreur ouverture pipe\n"); exit(1); } exit(0);

if (fork() == 0) { /* fils */ }

char c; }

close(p[1]);

while (read(p[0], &c, 1) != 0) printf("%c", c);

close(p[0]);

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 16


Plan

o Communication interprocessus

o Signaux

o Tubes/ pipes

o Synchronisation

o Terminologie : Thread, ressource partagée, exclusion


mutuelle, section critique..

o Critères de bonne synchronisation des processus

o Méthodes d’Attente active

o Méthodes d’Attente passive

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 17


Threads
Notion de Thread

 « une tâche indépendante à l’intérieur d’un processus»

 parfois appelé «processus léger»

 un thread ne peut pas vivre en dehors d’un processus

 besoin d’une vue mémoire

 un processus vivant a toujours au moins un thread

 «main thread» = thread qui exécute main()

 lorsque zéro thread  processus terminé

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 18


Threads

Rappel : Changement de contexte


TCB : Thread control block

Thread 1 Noyau Thread 2

T1 est actif
interruption copier les
registres CPU
ou Appel vers TCB1
System choisir T2
ssi P1 =ƒ P2: T2 est inactif
T1 est inactif
vidanger cache
et adopter PT
charger les de P2
registres CPU
depuis TCB2 RETI T2 est actif

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 19


Threads
API POSIX : Threads
# i n c l u d e <pthread.h>
/ * opaque t y p e d e f s * / p t h r e a d _ t , p t h r e a d _ a t t r _ t ;
/ / c r e a t e and s t a r t a new threa d
i n t pthread_create (pthread_t * t h read ,
pthread_attr_t * a t t r,
void * ( * f u n c t i o n ) ( v o i d * ) , void * a r g ) ;
/ / t e r m i n a t e t h e c u r r e n t threa d
void p t h r e a d _ e x i t ( v o i d * r e t v a l ) ;
/ / t e r m i n a t e another threa d
i n t p t h re a d _ c a n c e l ( p t h r e a d _ t t h r e a d ) ;
/ / w a i t f o r another threa d t o t e r m i n a t e
i n t p t h r e a d _ j o i n ( p t h r e a d _ t t h r e a d , void * * r e t v a l p ) ;

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 20


Threads Synchronisation

Accès concurrent à une ressource partagée


Exemple 1: Réservation de ticket

On suppose que deux clients accèdent en même temps afin de


réserver leur ticket

nb_ticket = 1
si nb_ticket > 0 alors
reserver_ticket
Que vaut la variable nb_ticket à la fin
nb_ticket  nb_ticket – 1 de l’exécution?
fsi

La variable nb_ticket doit être accédée par un seul processus à la fois.

Pr.HANIN Chapitre 4: Communication interprocessus & Synchronisation 21


Synchronisation

Accès concurrent à une ressource partagée

Exemple 2 : accès à une variable partagée entre deux threads

Question : que vaut var à la fin de l’exécution?

intuition : var==5

réalité : var==5 ou var==4 ou var==6

Pr . HANIN Chapitre 4: Communication interprocessus & Synchronisation 22


Synchronisation

Accès concurrent à une ressource partagée

Exemple 2 : Suite

Variable partagée
Thread A Thread B
v a r : 00000005
... ...
... ...
LOAD REGa←[ v ar] LOAD REGb←[ v a r]
INCR REGa DECR REGb
STORE REGa→[var] STORE REGb→[ var]
... ...
... ...

Remarque : A et B exécutés sur des (V)CPU distincts


► REGa et REGb (physiquement ou logiquement) distincts
23
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 23
Threads Synchronisation

Quelques exécutions possibles

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 24


Synchronisation Terminologies

Notion de race condition

VF «situation de concurrence», course critique, accès concurrents


Définition : race condition

Situation où le résultat du programme dépend de l’ordre dans


lequel sont exécutées les instructions des threads

Remarques
• Plusieurs accès concurrents à une ressource partagée
• variable globale, fichier, réseau, base de données...
• écriture+ écriture = problème
• écriture+ lecture = problème
• concurrence: parallélisme et/ou entrelacement
• i.e. quand on ne maîtrise pas l’ordre temporel des actions
• risques : corruption de données et/ou crash

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 25


Synchronisation Terminologies

Situation de concurrence : exemples


• deux écritures concurrentes= conflit

Thread A: x=10 Question : valeur finale de x?


Thread B: x=20

• une lecture et une écriture concurrentes= conflit


Init: x=5
Thread A: x=10 Question : valeur affichée?
Thread B: print(x)

Précepte : race condition = bug


Un programme dans lequel plusieurs tâches peuvent se retrouver
en situation de concurrence est un programme incorrect.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 26


Threads Synchronisation

Objectif : garantir l’exclusion mutuelle

Définitions
• Action atomique: action au cours de laquelle aucun état
intermédiaire n’est visible depuis l’extérieur
• Ressource critique: objet partagé par plusieurs threads et susceptible
de subir une race condition
• Section critique: morceau de programme qui accède a une
ressource critique
Idée : on veut que chaque section critique soit atomique

Définition : exclusion mutuelle


Interdiction pour plusieurs threads de se trouver simultanément à l’intérieur
d’une section critique

Idée : «verrouiller» l’accès à une section critique déjà occupée

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 27


Threads Exclusion mutuelle

Exclusion mutuelle par verrouillage

Variables partagées

Thread A int var = 5; Thread B


{ lock_t L; {
... ...
lock(L); lock(L);
var = var+1; var = var-1;
unlock(L); unlock(L);
... ...
} }

On voudrait ces deux méthodes atomiques:


• lock(L) pour prendre le verrou L en exclusivité
► un seul thread peut entrer en section critique
• unlock(L) pour relâcher le verrou L
► permet aux autres threads de le prendre à leur tour

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 28


Threads Exclusion mutuelle

Exclusion mutuelle : illustration

A entre en section critique A sort de la section critique

lock() unlock()
TA

lock() unlock()
TB temps
B attend
B veut entrer en B sort de la
B entre en
section critique section critique
section critique

29
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 29
Threads Exclusion mutuelle

Problème : comment garantir l’exclusion mutuelle ?

Autrement dit : comment implémenter l o c k ( ) et unloc k() ?


Propriétés souhaitables
• Exclusion mutuelle: à chaque instant, au maximum une seule tâche est en
section critique
• sinon risque de race condition
• Progression: si aucune tâche n’est en section critique, alors une tâche exécutant
l o c k ( ) ne doit pas se faire bloquer
• sinon risque de deadlock, en VF interblocage
• Équité: aucune tâche ne doit être obligée d’attendre indéfiniment avant de pouvoir
entrer en section critique
• sinon risque de starvation, en VF famine, privation
• Généralité : pas d’hypothèses sur les vitesses relatives ou sur le nombre des tâches en
présence
• on veut une solution universelle
• Bonus : implem simple, algo prouvable, exécution efficace...
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 30
Threads Synchronisation

Solution naïve (et incorrecte) : Attente active


partagé
i n t turn = 1;
Thread A Thread B
whi l e (1) wh i l e ( 1)
{ ... { ...
while(turn==2) while(turn==1)
{ / * a t t e n d re * / } { / * a t t e n d re * / }
/ / section critique / / section critique
turn = 2; turn = 1;
... ...
} }

• Exclusion mutuelle : OK
• Attente active : exécution pas très efficace ( ex. Consommation
de CPU)
• Problème : alternance stricte ► progression non garantie

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 31


Synchronisation

Solution naïve n o2 (incorrecte aussi) : Attente active

partagé
Thread A bool occup = 0; Thread B
while(1) while(1)
{ ... { ...
while(occup != 0) while(occup != 0)
{/* rien */ } {/* rien */ }
occup = 1; occup = 1;
/ / section critique / / section critique
occup = 0; occup = 0;
... ...
} }

• Progression : OK
• Exclusion mutuelle : non garantie
• Problème : consultation-modification non atomique

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 32


Synchronisation

Solutions : Attente active

Masquer les interruptions


• idée : empêcher tout changement de contexte
► dangereux, et inapplicable sur machine multiprocesseur

Approche purement logicielle


• idée :programmer avec des instructions atomiques
• autrefois seulement LOAD et STORE ► par ex. algo de Peterson
• de nos jours : TEST-AND-SET, COMPARE-AND-SWAP ► spin-lock
► attente active= souvent inefficace à l’exécution

Approche noyau :intégrer synchronisation et ordonnancement


• idée : programmer avec des instructions atomiques
• mais les cacher dans le noyau (derrière des appels système)
► permet de bloquer/ réveiller les threads au bon moment

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 33


Synchronisation Solutions

Mutex : définition

Verrou exclusif, ou mutex lock


• objet abstrait = opaque au programmeur
• deux états possibles : libre=unlocked ou pris= locked
• offre deux méthodes atomiques
• lock(L): si le verrou est libre, le prendre sinon, attendre qu’il se libère
• unlock(L): relâcher le verrou,
c.à.d. le rendre libre à nouveau

Remarques
• l o c k ( ) et unl oc k() implémentés comme appelssystème
• threads en attente = état BLOCKED dans l’ordonnanceur
• une file de threads suspendus pour chaque mutex
• invoquer unl oc k() réveille un thread suspendu (s’il y en a)
• attention : ordre de réveil non spécifié

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 34


Synchronisation Solutions

Mutex : définition

#include <pthread.h>

/ * opaque typ ed efs * / pthread_mutex_t, pthread_mutexattr_t;

/ / c re a te a new mutex lo c k
i n t pthread_mutex_init(pthread_mutex_t *mutex,
pthread_mutexattr_t * mu tex attr ) ;

i n t pthread_mutex_lock(pthread_mutex_t *mutex); i n t
pthread_mutex_unlock(pthread_mutex_t *mutex);

/ / attempt t o lo ck a mutex without blocking


i n t pthread_mutex_trylock(pthread_mutex_t *mutex);

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 35


Threads Synchronisation

Exclusion mutuelle : en résumé

Notion de« race condition»


• Plusieurs accès concurrents à une même variable
• accès non atomique ►données incohérentes

Section critique
• morceau de code qu’on veut rendre atomique
► exécution nécessairement en exclusion mutuelle

Solution : utiliser un mutex lock


• lo c k ( L ) ;
/* section critique */
unlock(L);
• nécessite que tous nos threads jouent le jeu

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 36


Plan

o Communication interprocessus

o Signaux

o Tubes/ pipes

o Synchronisation

o Terminologie : Thread, ressource partagée, exclusion


mutuelle, section critique..

o Critères de bonne synchronisation des processus

o Méthodes d’Attente active

o Méthodes d’Attente passive

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 37


Méthodes de synchronisation par l’attente passive

Problème des méthodes d’attente active:


- Consommation excessive de processeur quand l’accès à la SC est impossible
- Risque d’interblocage quand deux processus ou plusieurs processus attendent
indéfiniment les uns les autres.
- Difficulté de programmation
Idée: basculer le processus en attente de l'accès à une ressource partagée en mode bloqué,
jusqu'à ce que la ressource se libère, ce qui la fait basculer en mode prêt.
Les primitives SLEEP & WAKE UP
Deux primitives sont utilisées:
SLEEP: c’est un appel système qui suspend le processus appelant en attendant
qu’un autre processus le réveille.
WAKE UP: appel système qui permet de réveiller un processus donné.

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 38


Synchronisation Attente passive

Prod.-consomm. : solution naïve (et incorrecte)


Producteur-consommateur
Deux threads communiquent via une file FIFO partagée

P C

Producteur Consommateur
while(1) while(1)
{ {
item=produce(); item = fifo_get();
fifo_put(item); consume(item);
} }
Remarques :
• file = tampon circulaire de taille constante
• producteur doit attendre tant que la file est pleine
• consommateur doit attendre tant que la file est vide

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 39


Synchronisation
mécanisme de synchro universel Attente passive
Sémaphore

Producteur-consommateur
partagé
item_t b u ff e r [ N ];
i n t count=0;

Producteur Consommateur

i n t in =0; i n t out = 0 ;
whi l e (1) whi l e (1)
{ {
item=produce() while(count == 0 ) {}
while(count == N) {} item = b u f f e r [ o u t ] ;
buffe r[i n] =item; o u t = (out+1) N;
i n = (in+1) N; count = count - 1 ;
consume(item);
count = count +1 ; }
}
Observation : ce programme a des bugs de synchronisation
► Question : comment corriger le problème?

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 40


Synchronisation Attente passive
Producteur-consommateur
Tentative avec mutex 1 : deadlock
partagé
item_t buffer[N];
int count=0;
Producteur mutex L; Consommateur
int in = 0; int out = 0;
while(1) while(1)
{ {
item=produce() lock(L);
lock(L); while(count == 0) {}
while(count == N) {} item = buffer[out];
buffer[in] = item; out = (out+1) % N;
in = (in+1) % N; count = count - 1;
count = count + 1; unlock(L);
unlock(L); consume(item);
} }
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 41
Synchronisation Attente passive
Producteur-consommateur
Tentative avec mutex 2 : encore un deadlock
item_t buffer[N];
int count=0;
Producteur mutex L; Consommateur
int in = 0; int out = 0;
while(1) while(1)
{ {
item=produce() lock(L);
lock(L); while(count == 0) {}
while(count == N) {} unlock(L);
unlock(L); item = buffer[out];
buffer[in] = item; out = (out+1) % N;
in = (in+1) % N; lock(L);
lock(L); count = count - 1;
count = count + 1; unlock(L);
unlock(L); consume(item);
} }
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 42
Synchronisation Attente passive
Producteur-consommateur: A retenir

Hypothèses :
• file partagée de taille constante
• thread producteur doit attendre tant que la file est pleine
• thread consommateur doit attendre tant que la file est vide

Problèmes des solutions à base de mutex :


• mauvaise concurrence
• risques de deadlock
• attente active
Mauvaise nouvelle
Ce scénario est insoluble avec seulement lock()/unlock()

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 43


Synchronisation Attente passive

Notion de sémaphore
• objet abstrait =opaque au programmeur
• contient une variable entière k
• initialisée avec k > = 0 lors de la création du
sémaphore
• contient une file d’attente de threads bloqués
• offre deux méthodes atomiques P( ) et V()
P(S) V(S)
S .k = S.k - 1 ; S.k = S.k + 1 ;
i f ( S.k < 0 ) i f ( S.k <= 0 )
{ {
/ * suspendre l e th rea d /* rév e i l l e r l’un des
a p p e l a n t , e t l e m e t t re t h re a d s de la file
dans l a f i l e d ’ a t t e n t e d ’ a t t e n t e de S * /
de S * / }
}

44
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 44
mécanisme de synchro universel Sémaphore

Remarques

45
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 45
mécanisme de synchro universel Sémaphore

Producteur-consommateur avec Sémaphore

partagé
i t e m_t b u ff e r [ N ] ;
sem_t emptyslots=N;
sem_t f u l l s l o t s = 0 ;
Producteur Consommateur
in =0; out = 0 ;
whi l e (1) whi l e (1)
{ {
item=produce() P(fullslots);
P(emptyslots); item = b u f f e r [ o u t ] ; out
b u ff e r [i n] =item; i n = (out+1)%N;
= ( i n + 1 ) % N; V(empty slots);
V(fullslots); consume(item);
} }

Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 46


mécanisme de synchro universel Sémaphore

Sémpahores POSIX

#include <semaphore.h>
/ * opaque typedef * / sem_t;

/ / semaphore i n i t i a l i z a t i o n and destruction


i n t sem_init(sem_t *sem, i n t pshared, unsigned i n t
va l ue ) ;
i n t sem_destroy(sem_t *sem);

/ / synchronization methods
i n t sem_wait(sem_t *sem); / / wait = P =down
i n t sem_post(sem_t *sem); / / post =V =up =signal

47
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 47
mécanisme de synchro universel Sémaphore

Threads et synchronisation : en résumé


Processus VS thread VS mémoire virtuelle
• unité d’ordonnancement = thread
• unité d’isolation mémoire = espace d’adressage virtuel
• un processus = un espace d’adressage + un/plusieurs threads

Exclusion mutuelle
• stratégie permettant d’éviter les «race conditions»
• mécanisme : méthodes l o c k ( ) et unl oc k() atomiques

Sémaphore
• mécanisme de synchronisation universel
• P ( ) = «essayer de prendre un jeton, me suspendre si aucun dispo»
• V() = «ajouter un jeton et peut-être réveiller un autre thread»

48
Pr. HANIN Chapitre 4: Communication interprocessus & Synchronisation 48

Vous aimerez peut-être aussi