Chapitre - 4 - Communication Entre Processus - Synchronisation PDF
Chapitre - 4 - Communication Entre Processus - Synchronisation PDF
Chapitre - 4 - Communication Entre Processus - Synchronisation PDF
Pr HANIN
2022/2023
Plan
o Communication interprocessus
o Signaux
o Tubes/ pipes
o Synchronisation
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.
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
Principaux signaux
Signaux
Exemple : kill()
#include <sys/types.h>
#include <signal.h>
Retour:
• 0 si OK
• -1 en cas d'erreur
UCP
Anonymes : Pour mettre en relation des processus d’un même groupe (ses ancêtres et ses
descendants).
#include <unistd.h>
La valeur de retour de pipe() est 0 en cas de succès, -1 sinon (trop de descripteurs actifs,
ou de fichiers ouverts, etc...)
La communication est faite en mode FIFO (First In First Out). Premier écrit, premier
lu.
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.
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.
permet d’écrire les données se trouvant à l'emplacement mémoire pt, dans le tube
correspondant au descripteur d’écriture desc.
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
int p[2];
pipe(p);
................;
char txt[100];
close(P[1]);
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.
close(p[0]);
main() { /* communication PERE --> FILS par pipe */ write(p[1], message, 24);
if (fork() == 0) { /* fils */ }
char c; }
close(p[1]);
close(p[0]);
o Communication interprocessus
o Signaux
o Tubes/ pipes
o Synchronisation
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
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
intuition : var==5
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]
... ...
... ...
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
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
Variables partagées
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
• Exclusion mutuelle : OK
• Attente active : exécution pas très efficace ( ex. Consommation
de CPU)
• Problème : alternance stricte ► progression non garantie
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
Mutex : définition
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é
Mutex : définition
#include <pthread.h>
/ / 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);
Section critique
• morceau de code qu’on veut rendre atomique
► exécution nécessairement en exclusion mutuelle
o Communication interprocessus
o Signaux
o Tubes/ pipes
o Synchronisation
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
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?
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
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
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);
} }
Sémpahores POSIX
#include <semaphore.h>
/ * opaque typedef * / sem_t;
/ / 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
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