Title: Trois points importants:
1Communication interprocessus
- Trois points importants
- Comment partager les ressources?
- Concurrence pour l'utilisation des ressources
- Synchronisation
2Conditions de concurrence
Deux processus veulent accéder à la mémoire
partagée en même temps. Par exemple Les
processus A et B veulent utiliser la file
dimpression.
- A voit que la prochaine case disponible est 7
puis est remplacé par B - B voit que la prochaine case disponible est 7, y
place le nom de son fichier, puis est remplacé
par A - A place le nom de son fichier dans une case quil
croit libre écrasant le nom donné par B
3Sections Critiques (1)
- Lexclusion mutuelle est une méthode qui permet
de sassurer que si un processus utilise une
variable ou un fichier partagé, les autres
processus seront exclus de la même activité. - Une section critique (ou région critique) est la
partie du programme à partir de laquelle on
accède à la mémoire partagée.
4Sections Critiques (2)
- Quatre conditions pour obtenir l'exclusion
mutuelle - Un seul processus à la fois dans la section
critique - Aucune supposition sur le nombre et la vitesse
des CPUs - Aucun processus hors de la section critique ne
peut bloquer un autre processus. - Aucun processus ne doit attendre indéfiniment
pour entrer en section critique.
5Sections critiques (3)
- Exclusion mutuelle à l'aide des sections
critiques.
6Solutions à lexclusion mutuelle
- Désactivation des interruption
- Instruction disable
- On ne peut pas permettre aux usagers dutiliser
une telle instruction - Variable de verrou
- Un processus peut entrer seulement si VERROU0
Il met alors VERROU1 pour empêcher les autres
processus dentrer - Cette solution ne fonctionne pas!
7Alternance stricte
- Proposition de solution au problème de la section
critique - (a) Processus 0. (b) Processus 1.
8Solution de Peterson (1981)
define FALSE 0 define TRUE 1 define N 2
/ nombre de processus / int
turn / à qui le
tour ? / int interestedN
/ toutes valeurs initialement 0 (FALSE)
/ void enter_region(int i) / le
processus est 0 ou 1 / int other
/ nombre des autres processus /
other 1 - i / lopposé du
processus / interestedi TRUE /
montre que i est intéressé / turn i
/ au tour de i / while
(turn i interestedother TRUE)
/ instruction null / void
leave_region(int i) / i processus qui
quitte / interestedprocess FALSE
/ indique le départ de la section critique /
9Solution de Peterson (n processus)
// Il y a n processus. Chaque processus doit
franchir n-1 niveaux // avant d'accéder à la
section critique. int interestedn //
interestedij si le processus i est intéressé
a passer au niveau j int turn n-1 //
turnji si c'est au tour du processus i de
passer au niveau j void enter_region(int i)
// Le processus i veut entrer en section
critique for j1 to n-1 do
interestedij turnji L for
k1 to i-1, i1 to n if ( (turnji) and
(interestedk?j) ) goto L void
leave_region(int i) // Le processus i sort de
la section critique interestedi0
10L'instruction TSL (Test and Set Lock)
- TSL R, LOCK est une opération atomique
équivalente à - RLOCK
- LOCK1
-
enter_region TSL REGISTER,LOCK copie lock
dans le registre et le définit à 1 CMP
REGISTER,0 lock était-il à 0 ? JNE
enter_region s'il nétait pas à 0, boucle
RET retourne à lappelant entre en
section critique leave_region MOVE LOCK,0
stocke un 0 dans lock RET retourne à
lappelant
11L'instruction XCHG (Intel x86)
- XCHG R, LOCK échange le contenu de R et LOCK
- Cette instruction peut facilement remplacer TSL
enter_region MOVE REGISTER, 1 Mettre 1
dans REGISTER XCHG REGISTER,LOCK Échanger
REGISTER et LOCK CMP REGISTER,0 lock
était-il à 0 ? JNE enter_region s'il
nétait pas à 0, boucle RET retourne à
lappelant entre en section critique leave_regi
on MOVE LOCK,0 stocke un 0 dans lock
RET retourne à lappelant
12Opérations Sleep et Wakeup (1)
- Alternative aux solutions par attente active vues
jusquà présent. - Ex. Problème du producteur-consommateur
define N 100 /
nombre de connecteurs dans le tampon / int count
0 / nombre
déléments dans le tampon / void
producteur(void) int item while (TRUE)
item produire_item( ) /
génère lélément suivant / if (count
N) sleep( ) / si le tampon est plein,
entre en sommeil / ajouter_item(item)
/ place lélément dans le tampon /
count count 1 /
incrémente le décompte des éléments dans le
tampon / if (count 1)
wakeup(consommateur) / le tampon était
vide ? /
13Opérations Sleep et Wakeup (2)
void consommateur(void) int item while
(TRUE) if (count 0) sleep( )
/ si le tampon est vide, entre en sommeil /
item enlever_item( ) / prélève un
élément dans le tampon / count count -
1 / décrémente le décompte des
éléments dans le tampon / if (count N
- 1) wakeup(producteur) / le tampon était
plein ? / utiliser_item(item)
/ utilise lélément /
Que se passe-t-il si le producteur fait un wakeup
entre le moment ou le consommateur constate que
le tampon est vide et celui où il appelle sleep?
14Les sémaphores opérations Up et Down (1)
Solution de Dijkstra au problème des wakeup
perdus. Un sémaphore est une variable partagée
entre plusieurs processus et munie de deux
nouvelles instruction atomiques Down(S)
if (S0) sleep SS-1 Up(S)
SS1 if (S1) wakeup() // si des
processus sont endormis sur le
// sémaphore S alors
lun deux sera réveillé
15Les sémaphores
Résolution au problème du producteur-consommateur.
On utilise trois sémaphores
define N 100 / nombre
demplacements dans le tampon / typedef int
semaphore / les sémaphores sont un type
de variable int spécial / semaphore mutex 1
/ contrôle laccès à la section critique
/ semaphore empty N / compte les
emplacements vides dans le tampon / semaphore
full 0 / compte les emplacements
pleins / void producer(void) int item
while (TRUE) item produce_item(
) / génère quelque chose à placer dans le
tampon / down(empty) /
décrémente le décompte des emplacements vides /
down(mutex) / entre en
section critique / insert_item(item)
/ place un nouvel élément dans le tampon
/ up(mutex) /
quitte la section critique /
up(full) / incrémente le
décompte des emplacements pleins /
16Les sémaphores
void consumer(void) int item while
(TRUE) down(full)
/ décrémente le décompte des emplacements pleins
/ down(mutex) / entre en
section critique / item
remove_item() / prélève un élément dans le
tampon / up(mutex)
/ quitte la section critique /
up(empty) / incrémente le
décompte des emplacements vides /
consume_item(item) / fait quelque chose avec
lélément /
17Sémaphores sur Windows
HANDLE WINAPI CreateSemaphore( LPSECURITY_ATTRIBU
TES lpsa, LONG lInitialCount, //
Nombre de ressources initialement
disponibles LONG lMaximumCount, // Nombre
maximale de ressources LPCTSTR lpName )
DWORD WINAPI WaitForSingleObject( HANDLE
hSemaphore, DWORD dwMilliSeconds // Peut
être INFINITE ) BOOL WINAPI ReleaseSemaphore(
HANDLE hSemaphore, LONG lReleaseCount, //
Nombre de ressources à remettre LPLONG
lpPreviousCount // Reçoit le nombre de
ressource actuelle)
18Sémaphores sur Solaris
include ltsemaphore.hgt sem_t sem_open( char
nom, // Le premier caractère du nom doit être
'/' int oflag // O_CREAT ou O_CREAT
O_EXCL int mode // bits de permission int
valeur // valeur initiale ) int
sem_wait(sem_t psem) int sem_post(sem_t psem)
int sem_init( // sémaphore sans nom sem_t
psem, int pshare, // Si non nul, peut être
partagé avec d'autres processus int valeur //
NULL Attributs par défaut )
19Sémaphores sur Solaris
include ltsemaphore.hgt main() sem_t
my_semaphore int rc rc
sem_init(my_semaphore, 0, 10)
20Les mutex
- Les mutex sont des sémaphore qui ne peuvent
prendre que la valeur 0 ou 1. Ils servent à
réaliser lexclusion mutuel. - Voici comment utiliser linstruction TSL pour
implémenter - mutex_lock et mutex_unlock
mutex_lock TSL REGISTER,MUTEX copie
mutex pour enregistrer et définir mutex à 1
CMP REGISTER,0 mutex était-il à 0 ?
JZE ok si oui, il nétait pas
verrouillé, donc retourne CALL thread_yield
mutex est occupé planifie un autre thread
JMP mutex_lock réessaye plus
tard ok RET retourne à lappelant entrée
en section critique mutex_unlock MOVE
MUTEX,0 stocké un 0 dans mutex
RET retourne à lappelant
21Mutex sur Solaris
include ltpthread.hgt pthread_mutex_t mutex
PTHREAD_MUTEX_INITIALIZER int pthread_
mutex_lock(pthread_mutex_t pm) int
pthread_mutex_unlock(pthread_mutex_t pm)
int pthread_mutex_init( // mutex
dynamique pthread_mutex_t pm, const
pthread_mutexattr_t mattr // NULL Attributs
par défaut )
22Mutex sur Windows
HANDLE WINAPI CreateMutex ( LPSECURITY_ATTRIBUTE
S lpma, // Pour nos applications ce paramètre
// peut être mis à NULL BOOL
bInitialOwner, // True pour créer et posséder le
mutex LPTSTR lpName // Nom pour partager le
mutex avec d'autres processus
// ( Peut être
NULL) ) DWORD WINAPI WaitForSingleObject( HAND
LE hMutext, DWORD dwMilliSeconds // Peut
être INFINITE ) BOOL WINAPI ReleaseMutex(
HANDLE hMutex )
23Critical Section sur Windows
void WINAPI InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection ) void
WINAPI EnterCriticalSection( LPCRITICAL_SECTION
lpCriticalSection ) BOOL WINAPI
InitializeCriticalSectionAndSpinCount(
LPCRITICAL_SECTION lpCriticalSection, DWORD
dwSpinCount ) void WINAPI LeaveCriticalSection
( LPCRITICAL_SECTION lpCriticalSection )
24Critical Section sur Windows
// Variable globale CRITICAL_SECTION
CriticalSection DWORD WINAPI ThreadProc(
LPVOID lpParameter ) ... EnterCriticalSection
(CriticalSection) ... // Accès à la
ressource partagée. LeaveCriticalSection(Critical
Section) ... void main() ...
InitializeCriticalSection(CriticalSection)
... // Création des threads
DeleteCriticalSection(CriticalSection) ...
25Variables conditionelles
- Permet à un thread de se bloquer non pas à
lentrée dune région critique mais en fonction
dune certaine condition - définie par la valeur dune variable.
- Ex. Plusieurs threads se partage une variable P
quils incrémentent à tour de rôle. -
- Un des threads veut se bloquer tant que P
naura pas pas atteint une certaine valeur.
26Variables conditionelles sur Windows Vista
- VOID WINAPI InitializeConditionVariable
- PCONDITION_VARIABLE cond
- )
- BOOL WINAPI SleepConditionVariableCS( // De
façon atomique, bloque et - PCONDITION_VARIABLE cond, // relâche la
section critique - PCRITICAL_SECTION pcs,
- DWORD millisecond
- )
- VOID WINAPI WakeConditionVariable( //
Débloque un thread bloqué - PCONDITION_VARIABLE cond // sur la
variable de condition - )
- VOID WINAPI WakeAllConditionVariable( //
Débloque tous les threads bloqués - PCONDITION_VARIABLE cond // sur la
variable de condition - )
27Variables conditionelles sur Solaris
- pthread-cond_t cond PTHREAD_COND_INITIALIZER
- int pthread_cond_wait(
- pthread_cond_t cond,
- pthread_mutex_t mutex
- )
- int pthread-cond_signal(pthread_cond_t cond)
- int pthread_cond_broadcast(pthread_cond_t cond)
int pthread_cond_init( pthread_cond_t
cond, const pthread_condattr_t attr )
28Les barrières
- Utilisation des barrières
- Les processus s'approchent de la barrière
- Tous les processus sauf un sont bloqués
- Le dernier processus arrive, libérant les autres
29Les barrières sur Solaris
- int pthread_barrier_init(pthread_barrier_t
barrier, - const
pthread_barrierattr_t attr, - unsigned
count) - int pthread_barrier_wait(pthread_barrier_t
barrier) - int pthread_barrier_destroy(pthread_barrier_t
barrier)
30Passage de messages
- Deux primitives
- Send(destination, message)
- Receive(source, message)
- En labsence de message disponible, le récepteur
peut se bloquer jusquà ce que celui-ci arive.
31Le problème du producteur-consommateur avec N
messages
32File d'attente de message sur Solaris
- include ltsys/msg.hgt
- int msgget( key_t key, //IPC_PRIVATE ou une
valeur de clef valide - int msgflg ) // bits de permissison (
IPC_CREAT pour créer la file) - struct msgbuflong mtype, char mtext msg
- int msgsnd( int msqid,
- const void msgp, //pointeur sur le
message - size_t msgsz, // taille du message
- int msgflg) // 0 pour suspendre le
thread si la file est pleine -
- int msgrcv( int msqid,
- void msgp,
- size_t msgsz,
- long int mtype, // premier membre de msgbuf
- int msgflg) // 0 pour suspendre le
thread si la file est vide
33Le dîner des philosophes (1)
- Les philosophes mangent et pensent
- Mangent avec 2 fourchettes
- Prennet une seule fourchette à la fois
- Comment prévenir les interbloquages ?
34Le dîner des philosophes (2)
- Cette solution ne fonctione pas
35Le dîner des philosophes (3)
36Le dîner des philosophes (4)
37Le dîner des philosophes (5)
38Le problème des lecteurs et des rédacteurs
- Permet de modéliser les accès aux bases de
données. - Un processus qui écrit doit avoir un accès
exclusif à la base de données - Les processus qui lisent nont pas besoin ddun
accès exclusif.
39Le problème des lecteurs et des rédacteurs
40Le problème des lecteurs et des rédacteurs
41Le problème du barbier endormi (1)
42Le problème du barbier endormi (2)
43Le problème du barbier endormi (3)