add os & concurrent programmation (#22)
No files matched your search
@@ -164,6 +164,7 @@
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-xml.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-json.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-sql.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-pascal.js"></script>
|
||||
|
||||
<!----- Dark Theme ----->
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify-darklight-theme@latest/dist/index.min.js"> </script>
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
<header><h1>
|
||||
Programmation concurrente
|
||||
</h1></header>
|
||||
|
||||
Un programme concurrent est un programme non séquentiel.
|
||||
Soit l'expression arithmétique suivante : $(a+b) * (c+d)$.
|
||||
|
||||
***Programmation séquentiel***
|
||||
1. $x = (a+b)$
|
||||
2. $y = (c+d)$
|
||||
3. $x*y$
|
||||
|
||||
***Programmation concurrente***
|
||||
1. $x = (a+b) \qquad y = (c+d)$
|
||||
2. $x*y$
|
||||
|
||||
La programmation concurrente sur 1 CPU permet d'exploiter pleinement les périphériques parallèlement au processeur.
|
||||
Cela permet d'éviter de bloquer toutes les applications lorsqu'une seule est en attente d'une réponse.
|
||||
|
||||
La programmation concurrente sur plusieurs CPU permet en plus un gain de temps.
|
||||
|
||||
# Exclusion mutuelle
|
||||
un programme est une entité statique
|
||||
un processus est une entité dynamique
|
||||
|
||||
Les processus ne sont jamais totalement indépendants.
|
||||
Ils partagent des ressources (mémoire, fichiers, périphériques, variable, etc.)
|
||||
|
||||
Ceci peut conduire à des erreurs et doit donc être controlé.
|
||||
|
||||
- ***Section critique :*** partie du code qui accède à une ressource partagée.
|
||||
- ***Exclusion mutuelle :*** un seul processus à la fois peut accéder à la section critique.
|
||||
- ***Ressource critique :*** ressource qui doit être accédé en exclusion mutuelle
|
||||
|
||||
On pourrait éviter les problèmes d'exclusion mutuelle si on pouvait assurer que deux processus n'exécute jamais en même temps une section
|
||||
critique.
|
||||
On peut résoudre ce problème à l'aide de **mutex** ou **sémaphore**.
|
||||
|
||||
## Exclusion mutuelle par attente active
|
||||
|
||||
```pascal
|
||||
type processNum = 1..2;
|
||||
|
||||
module CS; /* Section critique */
|
||||
defines Enter, Leave; /* Primitive */
|
||||
|
||||
var
|
||||
request : array processNum of boolean;
|
||||
tour : processNum;
|
||||
procedure Enter(num: processNum);
|
||||
begin
|
||||
request[num] := true; /* Demande d'accès */
|
||||
tour := 3 – num; /* Autre processus */
|
||||
repeat
|
||||
/* Attendre que l'autre processus ait fini avec "not request" */
|
||||
/* Priorité si les deux processus demandent en même temps à la section critique
|
||||
grâce à "tour = num" */
|
||||
until (not request[3-num]) or (tour = num)
|
||||
end Enter;
|
||||
|
||||
procedure Leave(num: processNum);
|
||||
begin
|
||||
request[num] := false
|
||||
end Leave;
|
||||
|
||||
begin /* Initialisation */
|
||||
request[1] := false;
|
||||
request[2] := false
|
||||
end CS;
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
process P1;
|
||||
uses CS, Console;
|
||||
begin
|
||||
CS.Enter(1);
|
||||
Console.Write(”Error on hard disk !”);
|
||||
CS.Leave(1);
|
||||
end P1;
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
process P2;
|
||||
uses CS, Console;
|
||||
begin
|
||||
CS.Enter(2);
|
||||
Console.Write(”Printer not ready !”);
|
||||
CS.Leave(2);
|
||||
end P2;
|
||||
```
|
||||
|
||||
- si les processus *P1* et *P2* ne tentent pas de pénétrer simultanément dans la section
|
||||
critique, la variable *request[3-num]* est fausse et l'entrée en section critique est
|
||||
autorisée
|
||||
- si par contre les processus *P1* et *P2* tentent de pénétrer simultanément dans la section
|
||||
critique, la variable *tour* permet d'arbitrer entre les deux demandes. La variable
|
||||
*tour* (à la ligne 15) indique le numéro du processus élu
|
||||
|
||||
Cette méthode peut facilement être généralisée à n processus. Il suffit de faire *tour := n+1 – num* et
|
||||
*request[n+1-num]*.
|
||||
|
||||
Cette solution n'est pas satisfaisante, car elle consomme beaucoup de ressources CPU. En effet, un processus
|
||||
qui attend l'accès à la section critique est en attente active. Il est donc en boucle constante et consomme
|
||||
beaucoup de ressources CPU.
|
||||
|
||||
|
||||
## Exclusion mutuelle par masquage des interruptions
|
||||
Masquer les interruptions pour résoudre le problème de l'exclusion mutuelle.
|
||||
Plus d'interruption $=>$ plus de commutation de processus $=>$ plus de risque de violer l'exclusion mutuelle.
|
||||
|
||||
Le danger avec cette solution est le risque de perte d'information provenant des périphériques. Cela ne peut être une bonne solution
|
||||
que si la section critique est très courte. Il est dangereux de laisser la possibilité de masquer les interruptions à l'utilisateur.
|
||||
|
||||
|
||||
## Instruction TAS (TestAndSet)
|
||||
L'exclusion mutuelle par masquage des interruptions n'est pas possible dans une architecture multiprocesseur.
|
||||
Il est possible de résoudre le problème de l'exclusion mutuelle en utilisant l'instruction *TAS*.
|
||||
Elle permet de tester et de modifier une variable en **une seule instruction** assembleur.
|
||||
|
||||
|
||||
# Mutex
|
||||
Le mutex est utilisé pour bloquer l'accès simultané aux sections critiques avec les primitives suivantes :
|
||||
- ***block() :*** Il laisse passer un seul processus à la fois. Si la section est déjà bloquée, le processus et mis dans
|
||||
une file d'attente.
|
||||
```pascal
|
||||
procedure Block(var v:lock);
|
||||
begin
|
||||
if v.state = OPEN then
|
||||
v.state := CLOSE
|
||||
else
|
||||
block the process in the list "v.waiting"
|
||||
end if
|
||||
end Block;
|
||||
}
|
||||
```
|
||||
- ***release() :*** Il libère la section critique, si la file d'attente est vide. Sinon, il passe la main au processus
|
||||
suivant.
|
||||
```pascal
|
||||
procedure Release(var v:lock);
|
||||
begin
|
||||
if queue "v.waiting" not empty then
|
||||
unblock first process in the list "v.waiting"
|
||||
else
|
||||
v.state := OPEN
|
||||
end if
|
||||
end Release;
|
||||
}
|
||||
```
|
||||
Ces procédures sont elles même des sections critiques. Elles sont cepandant très courte et ne contiennent aucunes entrées-sorties.
|
||||
Elles peuvent donc être implémentées à l'aide d'une [Exclusion mutuelle par masquage des interruptions](#exclusion-mutuelle-par-masquage-des-interruptions)
|
||||
ou d'une [instruction TAS](#instruction-tas-testandset).
|
||||
|
||||
Les Mutex restent un outil primitif. Ils ne s'appliquent pas sur des problèmes plus complexes.
|
||||
|
||||
# Sémaphore
|
||||
Le sémaphore est une généralisation du mutex. Il permet de bloquer l'accès à une ressource partagée par plusieurs processus.
|
||||
Il limite l'accès à plusieurs même ressources utilisées par plusieurs processus.
|
||||
|
||||
Par exemple : les processus ont besoin d'imprimer et il y a plusieurs imprimantes à disposition.
|
||||
Le sémaphore va limiter l'accès au nombre d'imprimantes disponibles.
|
||||
|
||||
Les primitives de sémaphores sont :
|
||||
- ***P*** (Passeren = passer) appelé aussi *wait*, *up*, *get* ou *lock*
|
||||
```pascal
|
||||
procedure P(var s:semaphore);
|
||||
begin
|
||||
s.num := s.num – 1;
|
||||
if s.num < 0 then
|
||||
block the process at the end of the list "s.waiting"
|
||||
end if
|
||||
end P;
|
||||
```
|
||||
- ***V*** (Vrijgeven = libérer) appelé aussi *signal*, *down*, *release* ou *unlock*
|
||||
```pascal
|
||||
procedure V(var s:semaphore);
|
||||
begin
|
||||
s.num := s.num + 1;
|
||||
if s.num <= 0 then
|
||||
unblock first process in the list "s.waiting"
|
||||
end if
|
||||
end V;
|
||||
```
|
||||
|
||||
À l'initialisation, le sémaphore est initialisé au nombre de mêmes ressources disponibles.
|
||||
Ou alors, il est initialisé à 1 pour un mutex.
|
||||
Ou alors, il est initialisé à 0 pour un sémaphore binaire (file d'attente).
|
||||
|
||||
|
||||
## Interblocage
|
||||
L'interblocage est un problème qui peut survenir lorsqu'un ensemble de processus se bloquent mutuellement.
|
||||
On appelle aussi cela un **DEADLOCK**.
|
||||
|
||||
## Résolution reader / writter
|
||||
Le but est qu'il peut avoir plusieurs processus qui puisse lire la même ressource et aucun modifier la ressource.
|
||||
Sinon, **un** processus peut modifier la ressource et aucun peut lire.
|
||||
```cpp
|
||||
void BeginRead(void) {
|
||||
osSemaphoreAcquire(rw, osWaitForever);
|
||||
osSemaphoreAcquire(mutexNbReader, osWaitForever); // ENTER CRITICAL SECTION
|
||||
nbReader++;
|
||||
if(nbReader == 1) osSemaphoreAcquire(w, osWaitForever);
|
||||
osSemaphoreRelease(mutexNbReader); // EXIT CRITICAL SECTION
|
||||
osSemaphoreRelease(rw);
|
||||
}
|
||||
|
||||
void EndRead(void) {
|
||||
osSemaphoreAcquire(mutexNbReader, osWaitForever); // ENTER CRITICAL SECTION
|
||||
nbReader--;
|
||||
if(nbReader == 0) osSemaphoreRelease(w);
|
||||
osSemaphoreRelease(mutexNbReader); // EXIT CRITICAL SECTION
|
||||
}
|
||||
|
||||
void BeginWrite(void) {
|
||||
osSemaphoreAcquire(rw, osWaitForever);
|
||||
osSemaphoreAcquire(w, osWaitForever);
|
||||
}
|
||||
|
||||
void EndWrite(void) {
|
||||
osSemaphoreRelease(w);
|
||||
osSemaphoreRelease(rw);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
# Synchronisation
|
||||
|
||||
|
||||
Etat d'un processus :
|
||||
|
||||

|
||||
|
||||
Le processeur possède une liste de descripteur caractérisant chaque processus. Ces descripteurs de processus qui
|
||||
contiennent le registre de status et un pointeur sur sa stack. Ils sont utilisé pour faire des switching context :
|
||||
1. Le noyau va sauvegarder les registres de travail du processus en cours sur la stack.
|
||||
2. Il va sauvegarder aussi le registre de status et le pointeur de stack dans la liste de descripteurs.
|
||||
3. Il va prendre le descripteur du prochain processus et utiliser ses registres.
|
||||
4. Le processus continue jusqu'au nouveau switching context.
|
||||
|
||||
@@ -4,4 +4,6 @@ PTR - Programmation Temps Réel
|
||||
|
||||
- [XF](/infotro/PTR/XF.md)
|
||||
- [UML](/infotro/PTR/UML)
|
||||
- [RealTime](/infotro/PTR/RealTime)
|
||||
- [RealTime](/infotro/PTR/RealTime)
|
||||
- [SYS - Systèmes](/infotro/PTR/SYS)
|
||||
- [PCO - Programmation Concurrente](/infotro/PTR/PCO)
|
||||
@@ -0,0 +1,163 @@
|
||||
<header><h1>
|
||||
Introduction aux systèmes d'exploitation
|
||||
</h1></header>
|
||||
|
||||

|
||||
|
||||
Le système d'expoitation virtualise la partie hardward pour :
|
||||
- Simplifie l'utilisation
|
||||
- Gère les ressources physiques
|
||||
- Processeur
|
||||
- Mémoire principale
|
||||
- Entrées-sorties (disques, interfaces réseaux, ...)
|
||||
|
||||
L'OS gère les ressources à l'aide de technique de gestion des mémoires et de partage de ressources
|
||||
partageable entre plusieurs utilisateurs (ex : threads).
|
||||
Pour ce faire, il
|
||||
- connait à tout moment l'utilisateur d'une ressource
|
||||
- gère les accès à une ressource
|
||||
- accorde l'usage d'une ressource
|
||||
- évite les conflits
|
||||
|
||||
Les premiers systèmes d'exploitation étaient des systèmes à traitement par lots.
|
||||
Les programmes étaient regroupés en lots et exécutés les uns après les autres.
|
||||
Les programmes étaient chargés en mémoire et exécutés sans intervention de l'utilisateur.
|
||||
|
||||
## Machine à transistors
|
||||
|
||||
- Coûtent cher
|
||||
- Les utilisateurs ne peuvent pas interagir avec le système
|
||||
- Les utilisateurs écrivent leurs programmes en Fortran et en assembleur
|
||||
|
||||
<b><u>Fonctionnement :</b></u>
|
||||
1. Programmation d'une carte perforée en Fortran ou en assembleur
|
||||
2. L'opérateur prend les cartes perforées et les charge dans le compilateur
|
||||
3. L'opérateur récupère les cartes perforées compilées et les charge dans "l'ordinateur"
|
||||
4. L'ordinateur exécute le programme
|
||||
5. S'il y a une erreur, l'opérateur imprime l'image de la mémoire sur un listing et doit tout recommencer.
|
||||
|
||||
## Systèmes à traitement par lots
|
||||
Pour accélérer les opérations, deux méthodes sont utilisées :
|
||||
- ***Le traitement par lots (batch processing) :*** Regroupe et traite à la suite les travaux similaires
|
||||
- ***Le moniteurs d'enchaînement (linking monitor) :*** Les travaux sont automatiquement enchaîné et
|
||||
executé par un programme spécialisé (ancêtre des systèmes d'exploitation)
|
||||
- Une place mémoire lui est réservée dans la mémoire centrale qui se divise donc en une zone moniteur
|
||||
et une zone utilisateur
|
||||
|
||||
## Sysèmes avec spooling
|
||||
Les systèmes avec spooling permettent d'accéder simultanément à plusieurs périphériques d'entrée/sortie.
|
||||
Les travaux sont stockés dans une file d'attente (spool) et sont traités par un programme spécialisé.
|
||||
Le spooling permet de traiter plusieurs travaux en même temps.
|
||||
|
||||
La mémoire est partagée en quatre programmes :
|
||||
- Le programme d'entrée
|
||||
- Le programme d'enchaînement
|
||||
- Le programme de l'utilisateur
|
||||
- Le programme de sortie
|
||||
|
||||

|
||||
|
||||
## Système à multi-programmation
|
||||
La multi-programmation permet de partager le processeur entre plusieurs programmes.
|
||||
Chaque programme est chargé en mémoire et est exécuté en alternance.
|
||||
Dès qu'un programme doit lire des données ou écrire des résultats, il est mis en attente et un autre
|
||||
programme est exécuté afin d'optimiser l'utilisation du processeur.
|
||||
|
||||

|
||||
|
||||
La commutation de l'exécution d'un programme à un autre est assuré par l'**ordonnanceur** (scheduler).
|
||||
|
||||
*Inconvénients :* Les programmes cours, sont pénalisés car leur temps d'exécution dépend aussi des autres
|
||||
programmes en cours d'exécution.
|
||||
|
||||
|
||||
## Système à temps partagé
|
||||
Le système à temps partagé permet à plusieurs utilisateurs d'accéder simultanément à l'ordinateur.
|
||||
Chaque utilisateur dispose d'un temps d'utilisation du processeur (time slice) qui est très court (ex. 40 msec).
|
||||
|
||||

|
||||
|
||||
## Système temps réel
|
||||
Les systèmes temps réel doivent être capables réagire au rythme où les données arrivent et repartent.
|
||||
Ils ont des contraîntes plus hautes ques les systèmes à temps partagé, qui peuvent se permettent d'attendre
|
||||
alors qu'un système temps réel aurait des conséquences fâcheuses.
|
||||
|
||||
## Systèmes multi-processeur répartis
|
||||
Dans un système multi-processeur répartis, chaque processeur dispose de son propre système d'exploitation.
|
||||
Les systèmes d'exploitation communiquent entre eux pour partager les ressources.
|
||||
|
||||
|
||||
# Mécanisme d'entrées-sorties
|
||||
Pour accéder aux périphériques, le processeur utilise des mécanismes d'entrées sorties.
|
||||
|
||||
## Les registres d'un processeur
|
||||
Les registres contenus dans le processeur sont regroupés selon leur fonctionnalités
|
||||
- Registre généraux
|
||||
- Registre spécialisés
|
||||
- Le **registre d'instruction** IR (Instruction Register) contient l'instruction courante
|
||||
- Le **compteur ordinal** PC (Program Counter) contient l'adresse de l'instruction courante
|
||||
- Le **registre d'état** SR (Status Register) contient des informations sur l'état du processeur
|
||||
|
||||
Ces regstres caractérisent le contexte d'un programme. Il s'agit de la partie sauvegardée lors d'un
|
||||
*switching context* (changement de contexte).
|
||||
|
||||
|
||||
## Les registres d'un périphérique
|
||||
Les périphériques disposent, pour comuniquer avec le processeur, d'un certain nombre de registres:
|
||||
- **Registre de données** DR (Data Register) : Contient les données à lire ou à écrire
|
||||
- **Registre d'état** SR (Status Register) : Contient des informations sur l'état du périphérique
|
||||
- **Registre de commande** CR (Command Register) : Détermine les caractéristiques du périphérique
|
||||
|
||||
## Entrées-sorties en boucle d'attente
|
||||
Dans ce mode, le processeur attend que le périphérique soit prêt pour effectuer une opération.
|
||||
Le processeur effectue une boucle d'attente jusqu'à ce que le périphérique soit prêt.
|
||||
|
||||
1. Le processeur contrôle le registre d'état du périphérique
|
||||
2. Si le périphérique n'est pas prêt, le processeur effectue une boucle d'attente. S'il est prêt :
|
||||
3. Le processeur écrit les données dans le registre de données
|
||||
4. Le processeur écrit la commande dans le registre de commande
|
||||
5. Le périphérique effectue l'opération
|
||||
6. Le périphérique met à jour le registre d'état
|
||||
7. Le processeur lit les données dans le registre de données
|
||||
|
||||
Si le périphérique notifie le processeur :
|
||||
1. Le périphérique va changer son statut
|
||||
2. Le processeur va pouvoir aller chercher les données dans le registre de données
|
||||
|
||||
## Les interruptions
|
||||
Les interruptions permettent de signaler au processeur qu'un événement s'est produit.
|
||||
Le signal est la conséquence d'un évènement interne au programme et résultant de son exécution ou
|
||||
externe et indépendant de son exécution. Toute l'information nécessaire pour traiter l'interruption
|
||||
est regroupé en mémoire dans deux mots consécutis, appelés **vecteur d'interruption** (vector interrupt).
|
||||
On y trouve :
|
||||
- L'adresse de la routine de traitement de l'interruption
|
||||
- Le registre d'état du processeur pour cette routine.
|
||||
|
||||
Lorsqu'une interruption se produit, le processeur effectue un switching context et exécute la routine.
|
||||
|
||||
On distingue en général au moins trois niveaux d'interruption :
|
||||
- Les interruptions externes
|
||||
- Les exceptions internes
|
||||
- Les appels systèmes
|
||||
|
||||

|
||||
|
||||
## La DMA
|
||||
La [DMA](/infotro/SEm/DMA) (Direct Access Memory) permet de faire des transferts vers la mémoire rapidement.
|
||||
Le processeur laisse le controller DMA accéder au périphérique pour amener les données directement dans la
|
||||
mémoire et éviter de perdre du temps en passant par le processeur qui doit faire une copie des données.
|
||||
Elle est très utile lorsqu'il y a un grand nombre de données.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,13 @@ UML
|
||||
## Class
|
||||
|
||||
### Association bidirectionnel
|
||||
```mermaid
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
|
||||
classDiagram
|
||||
direction LR
|
||||
A -- B
|
||||
```
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
A - B : " "
|
||||
@@ -98,7 +105,26 @@ vt is Infection
|
||||
@enduml
|
||||
```
|
||||
|
||||
|
||||
## Sequence
|
||||
```mermaid
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
|
||||
sequenceDiagram
|
||||
participant a as A
|
||||
participant b as B
|
||||
a ->> b: synchrone / call
|
||||
a -) b: asynchrone
|
||||
activate b
|
||||
b -->> a: replay
|
||||
deactivate b
|
||||
|
||||
|
||||
b ->> b: sync auto call
|
||||
|
||||
b -) b: async auto call
|
||||
|
||||
```
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
participant A as a
|
||||
|
||||
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 38 KiB |
@@ -4,6 +4,8 @@
|
||||
- [XF](/infotro/PTR/XF.md)
|
||||
- [UML](/infotro/PTR/UML)
|
||||
- [RealTime](/infotro/PTR/RealTime)
|
||||
- [SYS - Systèmes](/infotro/PTR/SYS)
|
||||
- [PCO - Programmation Concurrente](/infotro/PTR/PCO)
|
||||
|
||||
|
||||
## [SDi - Système Distribué](/infotro/SDi/)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* [XF](/infotro/PTR/XF)
|
||||
* [UML](/infotro/PTR/UML)
|
||||
* [RealTime](/infotro/PTR/RealTime)
|
||||
* [SYS - Systèmes](/infotro/PTR/SYS)
|
||||
* [PCO - Programmation Concurrente](/infotro/PTR/PCO)
|
||||
* [SDi - Systèmes Distribués](/infotro/SDi)
|
||||
* [Transmission process](/infotro/SDi/transmission_process.md)
|
||||
* [IOT Technologies](/infotro/SDi/iot_technologies.md)
|
||||
|
||||