Reword and syntax corrections
This commit is contained in:
parent
b95fe8380b
commit
5c682b618a
1 changed files with 38 additions and 33 deletions
|
@ -42,17 +42,17 @@ void exit_sc ()
|
||||||
```
|
```
|
||||||
|
|
||||||
Nous avons donc besoin d'une solution non seulement valable pour un nombre
|
Nous avons donc besoin d'une solution non seulement valable pour un nombre
|
||||||
indéfinis de fils d'exécutions, mais aussi plus efficace.
|
indéfini de fils d'exécutions, mais aussi plus efficace.
|
||||||
|
|
||||||
## Une solution matérielle
|
## Une solution matérielle
|
||||||
|
|
||||||
Vu du processeur, une opération atomique ne peut être interompue par une autre.
|
Vu du processeur, une opération atomique ne peut être interompue par une autre.
|
||||||
Les processeurs modernes en comportent un certain nombres. La solution viens
|
Les processeurs modernes en comportent un certain nombre. La solution vient
|
||||||
donc des fabricant de processeurs.
|
donc des fabricant de processeurs.
|
||||||
|
|
||||||
Pour forcer l'exclusion mutuelle, nous en avons besoin d'une seule:
|
Pour forcer l'exclusion mutuelle, nous en avons besoin d'une seule:
|
||||||
`Test_and_Set`. C'est donc une instruction matérielle, voici une pseudo
|
`Test_and_Set`. C'est donc une instruction matérielle, voici une pseudo
|
||||||
implémentation en C:
|
implémentation en C :
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int test_and_set (int *verrou){
|
int test_and_set (int *verrou){
|
||||||
|
@ -104,12 +104,13 @@ threads en attente. Car seul le noyau peut endormir les processus.
|
||||||
|
|
||||||
## Les sémaphores
|
## Les sémaphores
|
||||||
|
|
||||||
On en a déjà parlé [en lpro]({{< ref"../../progsys/8_IPC">}} "Les IPC"). Ce sont
|
On en a déjà parlé [en lpro]({{<ref"../../progsys/8_IPC">}} "Les IPC"). Ce sont
|
||||||
des outils de haut-niveau, implémentés dans le noyau. Il se compose d'une
|
des outils de haut-niveau, implémentés dans le noyau. Il se compose d'une
|
||||||
structures contenant un entier positif et une liste de processus en attente et
|
structures contenant un entier positif, d'une liste de processus en attente et
|
||||||
de deux méthodes `P()` et `V()`. Il ont été inventés en 1962 par E. Dijsktra.
|
de deux méthodes `P()` et `V()`. Il ont été inventés en 1962 par E. Dijsktra.
|
||||||
|
|
||||||
Les méthodes permettent :
|
Les méthodes permettent :
|
||||||
|
|
||||||
* `P()`: attendre un jeton, le prendre lorqu'il devient disponible et continuer
|
* `P()`: attendre un jeton, le prendre lorqu'il devient disponible et continuer
|
||||||
son exécution.
|
son exécution.
|
||||||
* `V()`: remettre un jeton
|
* `V()`: remettre un jeton
|
||||||
|
@ -146,7 +147,7 @@ void barrier (int i)
|
||||||
count[i] = 0;
|
count[i] = 0;
|
||||||
V(mutex[i]);
|
V(mutex[i]);
|
||||||
|
|
||||||
// point
|
// point 2
|
||||||
for (int k=0; k < N-1; k++)
|
for (int k=0; k < N-1; k++)
|
||||||
V(wait[i]);
|
V(wait[i]);
|
||||||
}
|
}
|
||||||
|
@ -154,6 +155,7 @@ void barrier (int i)
|
||||||
```
|
```
|
||||||
|
|
||||||
Explication de code :
|
Explication de code :
|
||||||
|
|
||||||
* **point 1**: Utiliser des tableaux de 2 éléments permet de réutiliser notre
|
* **point 1**: Utiliser des tableaux de 2 éléments permet de réutiliser notre
|
||||||
fonction `barrier()` pour fixer plusieurs rendez-vous. Il suffit alors
|
fonction `barrier()` pour fixer plusieurs rendez-vous. Il suffit alors
|
||||||
d'apeller à tous de rôle `barrier(0);` et `barrier(1);`. Sans ça un
|
d'apeller à tous de rôle `barrier(0);` et `barrier(1);`. Sans ça un
|
||||||
|
@ -178,24 +180,24 @@ Un producteur appelle la fonction `put(element)` et un consommateurs
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define MAX 8
|
#define MAX 8
|
||||||
semaphore cons(0), prod(MAX)
|
semaphore conso(0), prod(MAX)
|
||||||
|
|
||||||
// Pour le consommateur
|
// Pour le consommateur
|
||||||
P(cons);
|
P(conso);
|
||||||
elemet = get();
|
elemet = get();
|
||||||
V(prod);
|
V(prod);
|
||||||
|
|
||||||
// Pour le producteur
|
// Pour le producteur
|
||||||
P(prod);
|
P(prod);
|
||||||
put(element);
|
put(element);
|
||||||
V(cons);
|
V(conso);
|
||||||
```
|
```
|
||||||
|
|
||||||
Le fonctionnement est ici assez simple :
|
Le fonctionnement est ici assez simple :
|
||||||
|
|
||||||
* **Pour le consomateur**:
|
* **Pour le consomateur**:
|
||||||
1. il prend un jeton sur le sémaphore `cons` s'il est disponible (ou attends
|
1. il prend un jeton sur le sémaphore `conso` s'il est disponible (ou
|
||||||
qu'il le soit)
|
attend qu'il le soit)
|
||||||
2. consomme l'élement
|
2. consomme l'élement
|
||||||
3. on relache celui sur `prod`. Cette dernière action permet de relancer
|
3. on relache celui sur `prod`. Cette dernière action permet de relancer
|
||||||
la production si la file était pleine (`prod` en attente).
|
la production si la file était pleine (`prod` en attente).
|
||||||
|
@ -204,8 +206,8 @@ Le fonctionnement est ici assez simple :
|
||||||
action permet d'arrêter la production s'il n'y a plus de jeton
|
action permet d'arrêter la production s'il n'y a plus de jeton
|
||||||
disponible.
|
disponible.
|
||||||
2. On produit ensuite l'élément
|
2. On produit ensuite l'élément
|
||||||
3. puis on relache le sémaphore `cons`. On réveille ansi notre consommateur
|
3. puis on relache le sémaphore `conso`. On réveille ansi notre
|
||||||
s'il dormait en attendant la disponibilité d'un élement
|
consommateur s'il dormait en attendant la disponibilité d'un élement
|
||||||
|
|
||||||
#### Multiple producteurs et consomateur
|
#### Multiple producteurs et consomateur
|
||||||
|
|
||||||
|
@ -213,15 +215,15 @@ Dans la vraie vie, il y souvent plusieurs consomateurs / producteurs. Le
|
||||||
problème devient alors plus complexe...
|
problème devient alors plus complexe...
|
||||||
|
|
||||||
Le code ressemble à celui ci-dessus, saut qu'il faut faire attention à ce qu'il
|
Le code ressemble à celui ci-dessus, saut qu'il faut faire attention à ce qu'il
|
||||||
y ai un seul consmateir à la fois sur `get()` et un seul producteur sur
|
y ai un seul consomateur à la fois sur `get()` et un seul producteur sur
|
||||||
`put(element)`. nous allons donc rajouter deux *"mutex"* :
|
`put(element)`. nous allons donc rajouter deux *"mutex"* :
|
||||||
|
|
||||||
```c {linenos=table,hl_lines=[6,8,13,15]}
|
```c {linenos=table,hl_lines=[6,8,13,15]}
|
||||||
#define MAX 8
|
#define MAX 8
|
||||||
semaphore cons(0), prod(MAX), mutex_c(1), mutex_p(1);
|
semaphore conso(0), prod(MAX), mutex_c(1), mutex_p(1);
|
||||||
|
|
||||||
// Pour le consomateir
|
// Pour le consommateur
|
||||||
P(cons)
|
P(conso)
|
||||||
P(mutex_v);
|
P(mutex_v);
|
||||||
element = get();
|
element = get();
|
||||||
V(mutex_v);
|
V(mutex_v);
|
||||||
|
@ -232,7 +234,7 @@ P(prod);
|
||||||
P(mutex_c);
|
P(mutex_c);
|
||||||
put(element);
|
put(element);
|
||||||
V(mutex_p);
|
V(mutex_p);
|
||||||
V(cons)
|
V(conso)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Problème des lecteurs rédacteurs
|
### Problème des lecteurs rédacteurs
|
||||||
|
@ -273,16 +275,18 @@ if(--nbr == 0) // last to leave
|
||||||
V(write_token);
|
V(write_token);
|
||||||
V(mutex_r);
|
V(mutex_r);
|
||||||
```
|
```
|
||||||
Pour les lecteur, il faut envoyer **un éclaireur** afin de savoir si un lecteur
|
|
||||||
|
Pour les lecteurs, il faut envoyer **un éclaireur** afin de savoir si un lecteur
|
||||||
est actif. Le problème est similaire à celui des producteur consommateurs sauf
|
est actif. Le problème est similaire à celui des producteur consommateurs sauf
|
||||||
qu'il faut savoir si notre lecteur est le premier *(ligne 12)*
|
qu'il faut savoir si notre lecteur est le premier *(ligne 12)*
|
||||||
|
|
||||||
De plus. afin que notre algorithme ne privilegie pas les lecteurs au
|
De plus, afin que notre algorithme ne privilegie pas les lecteurs au
|
||||||
détriment des rédacteur; ils peuvent même ne jamais rendre la main aux
|
détriment des rédacteur; ils pourraient même ne jamais rendre la main aux
|
||||||
rédacteurs. Pour pallier au problème, nous devons mettre en place une **salle
|
rédacteurs, nous devons mettre en place une **salle d'attente** *(ligne 8)*.
|
||||||
d'attente** *(ligne 8)*.
|
|
||||||
|
|
||||||
```c {linenos=table,hl_lines=[8,12]}
|
Voici le code pour les rédacteurs:
|
||||||
|
|
||||||
|
```c {linenos=table}
|
||||||
P(wait_room);
|
P(wait_room);
|
||||||
P(write_token);
|
P(write_token);
|
||||||
V(wait_room);
|
V(wait_room);
|
||||||
|
@ -296,7 +300,7 @@ Ce code est plutôt clair et ne comporte rien de particulier.
|
||||||
|
|
||||||
Les moniteurs sont des primitives de synchronisation initialement proposées dans
|
Les moniteurs sont des primitives de synchronisation initialement proposées dans
|
||||||
les langages objet. Il est utilisé actuellemt dans des langages tel que ADA ou
|
les langages objet. Il est utilisé actuellemt dans des langages tel que ADA ou
|
||||||
Java et implemente au sein de systèmes d'exploitation.
|
Java et implementé au sein de systèmes d'exploitation.
|
||||||
|
|
||||||
Le moniteur se positionne sur une classe et les mutexes sur ses methodes et sont
|
Le moniteur se positionne sur une classe et les mutexes sur ses methodes et sont
|
||||||
basés sur des variables condition. elle sont forcement privée et inaccessible à
|
basés sur des variables condition. elle sont forcement privée et inaccessible à
|
||||||
|
@ -317,7 +321,7 @@ public method g() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Il sont différent des *sémaphores*: il n'y a pas de jeton à prendre. Leur
|
Il sont différents des *sémaphores*, il n'y a pas de jeton à prendre. Leur
|
||||||
implémentation dans les systèmes d'exploitation est différente, elle se fait par
|
implémentation dans les systèmes d'exploitation est différente, elle se fait par
|
||||||
les les types `mutex_t` et `cond_t`:
|
les les types `mutex_t` et `cond_t`:
|
||||||
|
|
||||||
|
@ -400,9 +404,10 @@ tout comme les barrières, le code est ici bien plus simple. Et bien entendu il
|
||||||
n'y a pas d'attente active...
|
n'y a pas d'attente active...
|
||||||
|
|
||||||
Dans les codes ci-dessous, il est préféfable d'utiliser `while (nbe ...)` plutôt
|
Dans les codes ci-dessous, il est préféfable d'utiliser `while (nbe ...)` plutôt
|
||||||
qu'un `if (nbe ...)`. (Mais je ne sais plus pourquoi...)
|
qu'un `if (nbe ...)`. Si le processus se reveille, il faut s'arrurer que les
|
||||||
|
autres n'on pas déjà pris toutes les places disponibles.
|
||||||
|
|
||||||
Voici les variables nécessaires aux producteurs et au consomate
|
Voici les variables nécessaires aux producteurs et au consommateurs.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define MAX 8
|
#define MAX 8
|
||||||
|
@ -538,7 +543,7 @@ rwl_writeunlock(mylock);
|
||||||
|
|
||||||
## conclusion
|
## conclusion
|
||||||
|
|
||||||
Les sémaphores et moniyeurs sont implémentés au niveau du système d'exploitation
|
Les sémaphores et moniteurs sont implémentés au niveau du système d'exploitation
|
||||||
et utilient le matériel sous-jacent (`test_and_set`). Ces appels sont
|
et utilient le matériel sous-jacent (`test_and_set`). Ces appels sont
|
||||||
**coûteux**, nécessitent des **changements de contexte**. Dans les systèmes
|
**coûteux**, nécessitent des **changements de contexte**. Dans les systèmes
|
||||||
modernes, on leur préfèrera un **mix de primitive de synchronisation et de
|
modernes, on leur préfèrera un **mix de primitive de synchronisation et de
|
||||||
|
@ -548,11 +553,11 @@ pendant quelques cycles et se bloquera si elle n'est pas disponible.
|
||||||
Les moniteurs de Hoare sont en général préférés par les programmeurs cas comme
|
Les moniteurs de Hoare sont en général préférés par les programmeurs cas comme
|
||||||
on l'a vu, ils sont plus simple à implémenter.
|
on l'a vu, ils sont plus simple à implémenter.
|
||||||
|
|
||||||
Il eest intéressant aussi de parler des **FUTEX**, apparus en 2003 sur Linux et
|
Il est intéressant aussi de parler des **FUTEX**, apparus en 2003 sur Linux et
|
||||||
plus tard sous Windows 8 (sous l'appelation `wait_on_address` et brevete en
|
plus tard sous Windows 8 (sous l'appelation `wait_on_address` et breveté en
|
||||||
2013).
|
2013).
|
||||||
|
|
||||||
Ils utilisent des opétations atomiques sur des variables entières de 32bits *en
|
Ils utilisent des opérations atomiques sur des variables entières de 32bits *en
|
||||||
espace utilisateur* et deux operation bloquante si nécessaires:
|
espace utilisateur* et deux operation bloquante si nécessaires:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue