1. SYSTÈMES D‘EXPLOITATION
Université Blida 1
Faculté des Sciences
Département d’Informatique
Master SSI (Sécurité des Systèmes d’Informations)
Semestre 2
Mme AROUSSI
2017-2018
Disponible sur https://sites.google.com/a/esi.dz/s-aroussi/
2. PRÉAMBULE
Pré-requis: Cours (SE1 & Archi, 2ème année Licence).
Volume horaire hebdomadaire: 1.5H Cours + 1.5H TD + 1.5H TP.
Évaluation: Continu + Examen
Continu: Interrogation, Test TP, Projet , Devoir maison ,
Coefficient 3, Crédit 6 2
3. OBJECTIFS DU COURS
Approfondir certaines notions de base des systèmes
d’exploitation telles que la gestion de threads.
Apprendre à programmer les threads avec l’interface
POSIX.
3
4. GESTION DES THREADS
Mme AROUSSI
2017-2018
Disponible sur https://sites.google.com/a/esi.dz/s-aroussi/
Université Blida 1
Faculté des Sciences
Département d’Informatique
Master SSI (Sécurité des Systèmes d’Informations)
Semestre 2
5. Introduction aux Systèmes d’Exploitation
Partie I: Threads
Partie II: Ordonnancement
Partie III: Synchronisation
Partie IV: Communication
Partie V: Interruptions & Signaux
Annexes
5
PLAN DU COURS « GESTION DES THREADS »
6. 6
Pour qu'un ordinateur soit capable de faire fonctionner
un programme informatique (appelé parfois application ou logiciel),
la machine doit être en mesure d'effectuer un certain nombre
d'opérations préparatoires afin d'assurer les échanges entre
le processeur, la mémoire, et les ressources physiques(périphériques).
Le système d'exploitation (noté SE ou OS, abréviation du terme
anglais Operating System), est chargé d'assurer la liaison entre les
ressources matérielles, l'utilisateur et les applications (traitement de
texte, jeu vidéo, ...).
INTRODUCTION AUX S.E
7. 7
INTRODUCTION AUX S.E
Un Système d‘Exploitation peut être défini comme un logiciel qui ,
dans un appareil électronique, pilote les dispositifs matériels et reçoit
des instructions de l’utilisateur ou d’autres logiciels (ou applications).
Utilisent des langages
évolués (texte, chiffres,
image, son, dessin, …)
Utilisent un langage
binaire (0, 1)
8. 8
Les rôles du S.E sont divers :
1. Gestion des processeurs. Gérer l'allocation des processeurs entre les
différents programmes grâce à un algorithme d'ordonnancement.
2. Gestion des processus. Gérer l’exécution des processus en leur affectant les
ressources nécessaires à leur bon fonctionnement.
3. Gestion des mémoires. Gérer l'espace mémoire alloué à chaque processus.
4. Gestion des périphériques. Contrôler l'accès des processus aux ressources
matérielles par l'intermédiaire des pilotes.
5. Gestion des fichiers. Gérer la lecture et l'écriture dans le système de
fichiers et les droits d'accès aux fichiers par les utilisateurs et les applications.
6. Etc.
INTRODUCTION AUX S.E
9. 9
Le S.E est composé d'un ensemble de logiciels permettant de
gérer les interactions avec le matériel:
INTRODUCTION AUX S.E
11. 11
Générations des S.E:
1. Mono utilisateur/Mono tâche
C’est le cas le plus simple: Un seul utilisateur à la fois et une seule
tâche à la fois
Les systèmes d’exploitation des premiers micro-ordinateurs ne
dépassaient pas ce niveau de complexité.
2. Multitâches
Partager le temps du processeur entre plusieurs programmes
(tâches) impression de réalisation simultanée.
Le passage de l’exécution d’un programme à un autre peut être
initié:
Par les programmes eux-mêmes (coopératif)
Par le S.E (préemptif)
INTRODUCTION AUX S.E
12. 12
Générations des S.E:
3. Multiutilisateurs (temps partagé).
Plusieurs utilisateurs peuvent utiliser simultanément une
même machine pour des applications similaires ou
différentes
Chaque utilisateur a l’impression d’être le seul à utiliser
l’ordinateur.
4. Multiprocesseurs.
Un processeur central (maître) peut coordonner une série de
tâches sur plusieurs autres processeurs (esclaves).
Organisation à l’extérieur d’une série de tâches sur plusieurs
processeurs (systèmes répartis)
INTRODUCTION AUX S.E
13. 13
Générations des S.E:
5. Temps réels
Servent pour le pilotage et le contrôle des déroulements
externes (e.g. centrale électrique)
Doivent garantir des temps de réactions données pour des
signaux extérieurs urgents.
6. Distribués
Doivent permettre l’exécution d’un seul programme sur
plusieurs machines.
Distribuer les tâches et les remettre ensemble
Pour gros calculs, e.g. inversion de grandes matrices
INTRODUCTION AUX S.E
14. 14
Les S.E dédiés aux ordinateurs (bureau ou portable)
INTRODUCTION AUX S.E
Système Codage Utilisateur Tâche Processeur
MS-DOS ( Gates, 1981) 16 bits Mono Mono Mono
Windows
95/98/ME/
Microsoft (depuis
1991)
32 bits Multi
(coopératif)
Windows
NT/2000
Multi Multi
(préemptif)
Windows
XP/Vista/7/8/
10
32/64
bits
Multi
Unix (Ritchie & Thompson,1969) 32/64
bits
Linux (Torvalds & Stallman,
1992)
32/64
bits
MacOS (Jobs & Wozniak, 1984) 32 bits
16. 16
Popularité des S.E
INTRODUCTION AUX S.E
45%
28%
7%
6%
4%2%2%1%1%1%3%
Source NetMarketShare
(Janvier 2018)
Windows 7
Windows 10
Windows XP
Windows 8.1
Mac OS X 10.12
Mac OS X 10.11
Linux
Windows 8
Mac OS X 10.10
Mac OS X 10.13
18. Concept du processus
Concept du Thread
Pthread (POSIX Thread)
18
PLAN DE LA PARTIE I: THREADS
19. Concept du Processus:
Définition
Du programme au processus
Etats d’un processus
Bloc de Contrôle de Processus
Table des processus
Files des processus
Thread
Pthread (POSIX Thread)
19
PLAN DE LA PARTIE I: THREADS
20. 20
Un processus (ou tâche) représente l’exécution d’un
programme comportant des instructions et des ressources
(mémoire, processeur, imprimante, fichier de données,…).
C’est une entité dynamique (active) créée à un instant
donné, qui disparaît en général au bout d’un temps fini.
Un programme est une entité passive. Il peut
engendrer un ou plusieurs processus.
DÉFINITION DU PROCESSUS
22. 22
Le processus est une séquence d’actions (exécution
d’instructions), ayant une date de début (naissance) et
une date de fin. La date de début du processus correspond
à l’instant où il est pris en charge par le système
d’exploitation. La date de fin correspond à l’instant où le
processus finit son exécution de manière normale ou
anormale.
ETATS D’UN PROCESSUS
23. 23
Durant sa vie, un processus peut changer d’état à
plusieurs reprises. Ces états peuvent être résumés comme
suit :
ETATS D’UN PROCESSUS
24. 24
1. Nouveau : Le processus vient d’être créé.
2. Prêt : le processus est placé dans la file d’attente des
processus prêts, en attente d’affectation du processeur.
3. En exécution : le processus a été affecté à un processeur
libre. Ses instructions sont en exécution.
4. En attente : Le processus attend qu’un événement se
produise, comme l’achèvement d’une opération d’E/S ou la
réception d’un signal.
5. Terminé : le processus a terminé son exécution.
ETATS D’UN PROCESSUS
25. 25
Les états du processus sont représentés dans le système à
l'aide de structures de donnés, en général des files. Ces
structures de données contiennent des identificateurs de
processus ou des pointeurs vers les blocs de contrôle de
processus (PCB).
L'état nouveau : un vecteur composé de un ou plusieurs éléments
contient les identificateurs des processus crées en attende
d’admission.
FILES DES PROCESSUS
26. 26
L'état prêt peut être représenté par une ou plusieurs files : une
file par classe de processus (processus système, processus temps
réel, processus temps partagé) ou une file par priorité.
L'état bloqué (en attente): on peut trouver une file par événement,
signal ou ressource attendu (file des processus en attente de
l'imprimante, file des processus en attente de fin d'E/S sur le
disque,...).
FILES DES PROCESSUS
27. 27
Pour suivre son évolution, le SE
maintient pour chaque
processus une structure de
données particulière appelée
bloc de contrôle de processus
(PCB : Process Control Bloc) et
dont le rôle est de reconstituer
tout le contexte du processus.
BLOC DE CONTRÔLE DE PROCESSUS
28. 28
Les informations contenues dans un PCB peuvent être
regroupées en deux classes:
Informations nécessaires à l'exécution du processus
appelé le contexte d’un processus.
Informations nécessaires à la gestion du processus.
BLOC DE CONTRÔLE DE PROCESSUS
29. 29
Le contexte d'un processus est le sous-ensemble de la
machine que les actions (instructions) du processus
peuvent modifier ou consulter.
Il est défini par le contexte du processeur : registres internes (mot
d'état) et registres adressables, l'espace mémoire utilisé par le
programme et les données du processus et la pile d'exécution.
Ce contexte permet de reprendre l'exécution d'un processus qui a
été interrompu (c'est à dire les informations sauvegardées à
chaque changement d'état du processus ou commutation).
BLOC DE CONTRÔLE DE PROCESSUS
30. 30
Le contexte d'un processus permet de reprendre
l'exécution d'un processus qui a été interrompu (c'est à
dire les informations sauvegardées à chaque changement
d'état du processus ou commutation).
BLOC DE CONTRÔLE DE PROCESSUS
31. 31
Les informations de gestion permettent l'identification et
la gestion des processus. On peut trouver:
Identificateur du processus (PID) : identificateur attribué par le
système (noyau). Tout processus est identifié par un
identificateur unique (non modifiable) qui lui est propre et qui le
caractérise. L'identificateur permet de distinguer tout processus
de façon non ambiguë.
Nom symbolique (facultatif) : nom attribué par l'utilisateur,
Priorité,
Etat du processus,
BLOC DE CONTRÔLE DE PROCESSUS
32. 32
Les informations de gestion permettent l'identification et
la gestion des processus. On peut trouver:
Quantum ou temps maxi cpu restant à consommer
Pointeurs sur PCB des processus parents (père , fils,…)
Informations sur l’état des Entrées/Sorties :
Pointeur sur table des descripteurs des Fichiers ouverts,
Entrées/sorties en cours,…
Informations de comptabilité (temps CPU consommé, temps
d’attente, nombre d'entrées/sorties effectuées, ...)
BLOC DE CONTRÔLE DE PROCESSUS
33. 33
Le S.E. maintient dans une table appelée «table des
processus» les informations sur tous les processus créés.
Cette table permet au SE de localiser et gérer tous les
processus.
TABLE DES PROCESSUS
34. Concept du Processus
Concept du Thread:
Définition
Multithreads
Table des threads
Bloc de Contrôle de thread
Etats du thread
Implémentation du multithreads
Avantages threads/processus
Pthread (POSIX Thread)
34
PLAN DE LA PARTIE I: THREADS
35. 35
Thread ("processus léger") : unité d’exécution rattachée à un
processus, chargée d’exécuter une partie du processus.
DÉFINITION
Unité de ressource
Unité d’exécution
Processus
36. 36
Un processus est un programme qui
s’exécute selon un chemin unique
(compteur ordinal). On dit qu’il a un flot
de contrôle unique (un seul thread).
De nombreux systèmes d’exploitation
modernes offrent la possibilité d’associer
à un même processus plusieurs chemins
d’exécution. On parle du multithread
qui permet d’exécuter simultanément des
parties d'un même processus. Chaque
partie correspond à un chemin
d'exécution du processus.
Process
Thread
MULTITHREADS
37. 37
Lorsqu’un processus est créé, un seul thread (qui exécute
le programme principal, habituellement la fonction main)
est associé au processus. Ce thread (appelé le thread
principal) peut en créer d’autres threads (appelés threads
secondaires).
L’ensemble de tous les threads créés est enregistré dans
une table appelé «table des threads».
Chaque entrée de cette table contient une structure de
données particulière appelé bloc de contrôle de thread
(TCB : Threads Control Bloc),
TABLE DES THREADS
38. 38
Comme le PCB, le TCB contient des informations
nécessaire à
l'exécution du thread appelé le contexte d’un thread.
Ce contexte permet de reprendre l'exécution d'un
thread qui a été interrompu,
Informations nécessaires à la gestion du thread.
BLOC DE CONTRÔLE DE THREAD
39. 39
Le processus est vu comme étant un ensemble de
ressources (code exécutable, segments de données, de
fichiers, de périphériques, etc.) que ses threads partagent.
TCB: CONTEXTE DU THREAD
40. 40
Chaque thread a cependant, en plus des ressources
communes, sa propre zone de données ou de variables
locales, sa propre pile d'exécution, ses propres registres et
son propre compteur ordinal.
TCB: CONTEXTE DU THREAD
41. 41
Le TCB contient des informations du thread permettant
l'identification et la gestion du thread. On peut trouver:
Identificateur du thread (TID)
Priorité,
Etat du thread
Quantum restant à consommer
Pointeurs sur TCB des threads parents (père , fils,…)
Informations sur l’état des Entrées/Sorties
etc
TCB: INFORMATIONS DE GESTION
42. 42
Comme le processus, le thread peut passer par plusieurs
états (Nouveau, Prêt, En exécution, En attente, Terminé):
ETATS D’UN THREAD
43. 43
L’implémentation du multithreads varie
considérablement d’une plateforme à une autre. On
distingue trois modèles :
Plusieurs-à-un: les threads sont gérés au niveau
utilisateur (threads utilisateur):
Un-à-un: les threads sont gérés au niveau du noyau
(threads noyau).
Plusieurs à plusieurs: les threads sont gérés à deux
niveaux (threads hybrides).
IMPLÉMENTATION DES MULTITHREADS
44. 44
Les threads utilisateur sont implantés dans une
bibliothèque (niveau utilisateur) qui fournit un support
pour les gérer.
Exemple: Les threads Java sont gérés par la machine
virtuelle Java (JVM).
THREADS UTILISATEUR
45. 45
Les threads utilisateur ne sont pas gérés par le noyau; Le
noyau gère les processus (table des processus) et ne se
préoccupe pas de l’existence des threads (modèle
plusieurs-à-un).
THREADS UTILISATEUR
46. 46
Lorsque le noyau alloue le processeur à un processus, le
temps d’allocation du processeur est réparti entre les
différents threads du processus (cette répartition n’est pas
gérée par le noyau).
THREADS UTILISATEUR
47. 47
Avantages:
Les threads utilisateur sont généralement créés, et gérés
rapidement.
Ils facilitent la portabilité (comparativement aux autres
implémentations)
Inconvénients :
À tout instant, au plus un thread par processus est en cours
d’exécution. Cette implémentation n’est pas intéressante pour des
systèmes multiprocesseurs.
Si un thread d’un processus se bloque, tout le processus est bloqué.
Pour pallier cet inconvénient, certaines librairies transforment les
appels système bloquants en appels système non bloquants.
THREADS UTILISATEUR
48. 48
THREADS NOYAU
Les threads noyau sont directement supportés par le
système d’exploitation qui se charge de leur gestion. Un
temps CPU est alloué à chaque thread (modèle un-à-un).
Exemple: Linux ne fait pas de distinction entre les processus et les
threads qui sont communément appelés tâches.
49. 49
THREADS NOYAU
Si un thread d’un processus est bloqué, un autre thread du
processus peut être élu par le noyau. Cette
implémentation est plus intéressante pour les systèmes
multiprocesseurs.
50. 50
THREADS NOYAU
Un processus peut ajuster les niveaux de priorité de ses
threads. Par exemple, un processus peut améliorer son
interactivité en assignant : une forte priorité à un thread
qui traite les requêtes des utilisateurs et une plus faible
priorité aux autres.
Inconvénients :
Performance (gestion plus coûteuse)
Les programmes utilisant les threads noyau sont moins
portables que ceux qui utilisent des threads utilisateur.
51. 51
THREADS HYBRIDE
Threads hybride combinent les avantages des deux
approches:
Existence de threads noyau (qui sont gérés par le noyau)
Et des threads utilisateur sont multiplexées dessus
52. 52
THREADS HYBRIDE
Un ensemble de threads d’un même processus peut être
associés à un ensemble de threads noyau (modèle
plusieurs à plusieurs).
Inconvénient : mise en œuvre plus complexe
53. 53
THREADS HYBRIDE
Exemple: Threads Solaris
Chaque LWP (processus poids léger) supporte
un ou plusieurs threads utilisateur et
correspond à un thread noyau.
54. 54
Réactivité (le processus peut continuer à s’exécuter même
si certaines de ses parties sont bloquées),
Partage de ressources (facilite la coopération, améliore la
performance),
Économie d’espace mémoire et de temps. Il faut moins de
temps pour créer et terminer un thread (sous Solaris, la
création d’un processus est 30 fois plus lente que celle
d’un thread) et pour commuter entre deux threads d’un
même processus.
AVANTAGES DES THREADS/PROCESSUS
55. Concept du processus
Concept du Thread
Pthread (POSIX Thread)
Introduction
Convention
Gestion des threads
55
PLAN DE LA PARTIE I: THREADS
56. 56
De nombreux S.E permettent aujourd’hui la
programmation multithreads.
La bibliothèque pthread (posix thread),
conforme à la norme IEEE POSIX4.a, s’est imposée. Elle
fournit des primitives pour gérer les threads. Ces
primitives sont similaires à celles fournies par diverses
autres bibliothèques (Solaris, Windows) ou langages
(Java).
Les pthreads sont indépendants de leur implémentation
(threads utilisateur, noyau et hybride)
INTRODUCTION
57. 57
La norme POSIX est l’acronyme Portable Operating System
Interface for uniX ou interface portable pour les systèmes
d'exploitation.
Elle a initialement été mise en place pour les systèmes de type
UNIX mais d'autres systèmes d'exploitation comme Linux et
Windows sont aujourd'hui conformes à POSIX.
INTRODUCTION À LA NORME POSIX
58. 58
La norme POSIX définit une interface de
programmation standard en langage C, i.e. un ensemble
de structure de données et de fonctions mise à disposition
par le S.E
Cette norme a été développée par l'IEEE (Institute of
Electrical and Electronic Engineering) et standardisée
par l'ANSI (American National Standards Institute) et
l'ISO (International Standards Organisation).
INTRODUCTION À LA NORME POSIX
59. 59
Le but de POSIX est d'obtenir la portabilité des logiciels
au niveau de leur code source.
Un programme qui est destiné à un S.E qui respecte
POSIX doit pouvoir être adapté à moindre frais sous
n'importe quel autre système POSIX.
En théorie, le portage d'une application d'un système
POSIX vers un autre doit se résumer à une compilation
des sources du programme.
INTRODUCTION À LA NORME POSIX
60. 60
Le standard POSIX est divisé en plusieurs sous-standards :
POSIX.1 (IEEE Std 1003.1-1990), Interface de base d’accès au
système :
gestion des processus (fork, exec, kill …)
fichiers et terminaux (open, fopen , fgetc, dup ,fcntl ,mkdir …)
information runtime (getpid, cuerid, uname …)
signaux de base (signal, raise, sigaction … )
gestion mémoire (malloc, memcpy, free …)
gestion du temps ( time, clock …)
exécution (setjmp, longjmp …)
communication (pipe, mkfifo (named pipes), setbuf stream, …)
INTRODUCTION À LA NORME POSIX
61. 61
Le standard POSIX est divisé en plusieurs sous-standards :
POSIX.4 (IEEE Std 1003.1b-1993), extension pour le temps réel :
l'ordonnancement
les signaux en temps réel
les horloges et les timers
les sémaphores
le passage de messages
la mémoire partagée
les entrées-sorties synchrones et asynchrones
les outils de verrouillage de la mémoire
INTRODUCTION À LA NORME POSIX
62. 62
Le standard POSIX est divisé en plusieurs sous-standards :
POSIX.4a (IEEE Std 1003.1c-1995), extension sur les threads :
la création, le contrôle et la suppression des threads
l'ordonnancement des threads
la synchronisation des threads
l'interception des signaux (Signal Handling)
POSIX.4b (IEEE Std 1003.1d-1995), plus d’extension sur le
temps réel :
Gestion des interruptions;
INTRODUCTION À LA NORME POSIX
63. 63
Un programme C utilisant la bibliothèque pthread doit
disposer de l'entête suivant : #include <pthread.h>
Les variables pthread sont des objets:
pthread_t : identifiant d'un thread
pthread_attr_t : attribut d'un thread
pthread_mutex_t : mutex (exclusion mutuelle)
pthread_mutexattr_t : attribut d'un mutex
pthread_cond_t : variable de condition
pthread_condattr_t : attribut d'une variable de condition
pthread_key_t : clé pour accès à une donnée globale réservée
pthread_once_t : initialisation unique
CONVENTION
64. 64
Une fonction pthread renvoie 0 en cas de succès et valeur
différente de NULL en cas d'échec.
En général, le nom de la fonction dépend du type de l'objet
auquel elle s’applique.
Enlever le _t du type de l'objet
Ajouter un suffixe précisant le rôle de la fonction. Exemple:
_init : initialiser un objet.
_destroy: détruire un objet.
_create : créer un objet.
_getattr : obtenir l'attribut attr des attributs d'un objet.
_setattr : modifier l'attribut attr des attributs d'un objet.
CONVENTION
65. 65
En général, le nom de la fonction dépend du type de l'objet
auquel elle s’applique.
Enlever le _t du type de l'objet
Ajouter un suffixe précisant le rôle de la fonction (e.g.
init, destroy, create, getattr, setattr, …)
Exemples :
pthread_create : crée un thread (objet pthread_t).
pthread_mutex_init : initialise un objet du type
mutex
CONVENTION
66. 66
Un pthread :
est identifié par un identificateur unique TID (Thread
Identifier).
exécute une fonction passée en paramètre lors de sa
création.
possède des attributs.
peut se terminer (pthread_exit) ou être annulé par un
autre thread (pthread_cancel).
peut attendre la fin d'un autre thread (pthread_join).
GESTION DES THREADS: DÉFINITION
67. 67
Les attributs d’un thread indiquent ses différentes
propriétés: son type (noyau ou utilisateur), sa stratégie
d'ordonnancement, sa priorité, tâche joignable/détachable,
la taille de la pile, etc.
Ils sont passés au moment de la création de thread:
Paramètre du type pthread_attr_t
Ils peuvent être initialisés avec les valeurs par défaut :
int pthread_attr_init (pthread_attr_t *attrib) ;
GESTION DES THREADS: ATTRIBUTS
68. 68
Chaque attribut possède un nom utilisé pour
construire les noms de deux types fonctions :
pthread_attr_getnom (pthread_attr_t *attr, …):
Extraire la valeur de l'attribut nom de la variable attr
pthread_attr_setnom (pthread_attr_t *attr, …) :
Modifier la valeur de l'attribut nom de la variable attr
GESTION DES THREADS: ATTRIBUTS
69. 69
Noms des attributs sont:
scope (int): thread native (noyau) ou pas
stackaddr (void *): adresse de la pile
stacksize (size_t): taille de la pile
detachstate (int): thread joignable ou détaché
schedpolicy (int): type d'ordonnancement
schedparam (sched_param *): paramètres pour
l'ordonnanceur
inheritsched (int): ordonnancement hérité ou pas.
GESTION DES THREADS: ATTRIBUTS
70. 70
Chaque attribut possède un nom utilisé pour construire les noms de
deux types fonctions :
pthread_attr_getnom (pthread_attr_t *attr, …): Extraire la valeur de
l'attribut nom de la variable attr
pthread_attr_setnom (pthread_attr_t *attr, …) : Modifier la valeur de
l'attribut nom de la variable attr
Exemple: Obtenir/modifier la taille de la pile d'un
thread
int pthread_attr_getstacksize (const pthread_attr_t *attributs,
size_t *taille);
int pthread_attr_setstacksize (const pthread_attr_t *attributs,
size_t taille);
GESTION DES THREADS: ATTRIBUTS
71. 71
La création d'un thread est réalisée avec la fonction suivante :
int pthread_create(pthread_t *thd_id, pthread_attr_t *attr,
void* (*start_routine)(void*), void *arg);
Thd_id : pointeur de type pthread_t contenant l'identificateur
du thread créé ;
attr : si NULL, le thread est crée par les attributs par défaut.
start_routine : le nom de la fonction C qui sera exécutée par le
thread créé ;
arg : pointeur correspond aux variables passées en paramètre à
la fonction start_routine. Il vaut NULL si aucun paramètre
n'est passé à la fonction ;
Comme valeur de retour, la fonction pthread_create renvoie 0 si
tout s'est bien passé et un nombre négatif sinon.
GESTION DES THREADS: CRÉATION
72. 72
Thread principal versus Threads annexes
La création d'un processus donne lieu à la création du
thread principal (thread main).
Un retour à la fonction main entraîne la terminaison
du processus et par conséquent la terminaison de tous
ses threads.
Un thread créé par la primitive pthread_create dans la
fonction main est appelée un thread annexe.
GESTION DES THREADS: CRÉATION
73. 73
Thread principal versus Threads annexes
Un thread créé par la primitive pthread_create dans la
fonction main est appelée une thread annexe.
Un retour de la fonction correspondante au thread
annexe ou un appel à la fonction pthread_exit
entraînent la terminaison du thread annexe (aucun
effet sur l'existence du processus ou des autres
threads).
L'appel à exit par un thread annexe provoque la
terminaison du processus et de tous les autres threads.
GESTION DES THREADS: CRÉATION
74. 74
Exemple 1:
GESTION DES THREADS: CRÉATION
# include <stdio.h>
# include <pthread.h>
void *fct (void *arg)
{
printf ("Je suis le thread %lu n", pthread_self());
printf ("J ai recu l argument %s n", (char*) arg);
}
int main ()
{
pthread_t thd;
printf (" Le processus %d lance un threadn", getpid());
if (pthread_create (&thd, NULL, fct, "BONJOUR"))
perror ("pthread_createn");
else
pthread_join(thd, NULL);
return 0;
}
75. Exemple 1: Logigramme
GESTION DES THREADS: CRÉATION
Debut
Déclaration
PrintfEcran
Fin
p_create
= 0
Non
perror
Oui
fctp_join
Debut fct
Printf
Fin fct
pthread_self
Printf
Thread principal
Thread annexe « thd »
76. 76
Obtention de l'identificateur du thread courant :
pthread_t pthread_self (void);
Comparaison entre deux identificateurs de threads
pthread_t pthread_equal(pthread_t t1, pthread_t t2);
Test d'égalité : renvoie une valeur non nulle si t1 et t2
identifient le même thread.
GESTION DES THREADS: TID
77. 77
La terminaison d'un thread est réalisée avec la fonction
suivante :
void pthread_exit(void *status);
Statut sert à récupérer la valeur de retour et l’état de
terminaison. Elle est accessible aux autres threads du
même processus par l'intermédiaire de la fonction
pthread_join.
GESTION DES THREADS: TERMINAISON
78. 78
Attendre la fin d’un thread: Lorsqu'un thread crée un autre thread,
s'il ne lui est pas explicitement indiqué d'attendre la fin d'exécution du
thread fils, alors à sa terminaison il forcera l'arrêt du thread fils. Pour
éviter cela, on utilise la fonction pthread_join:
void pthread_join(pthread_t thd_id, void**statut)
Thd_id : représente l'identificateur du thread que le thread
créateur doit attendre.
statut sert à récupérer la valeur de retour et l’état de terminaison.
Il vaut NULL si le thread ne renvoie aucune valeur.
GESTION DES THREADS: TERMINAISON
79. 79
void pthread_join(pthread_t *thd_id, void**statut)
Le thread thd_id doit appartenir au même processus que le thread
appelant.
Si le thread thd_id n'est pas encore terminée, le thread appelant
sera bloqué jusqu'à ce que le thread thd_id se termine.
Si le thread thd_id est déjà terminée, le thread appelant n'est pas
bloquée.
Le thread thd_id doit être joignable.
Un seule thread réussit l'appel.
Les ressources de thread sont alors libérées.
GESTION DES THREADS: TERMINAISON
80. 80
Exemple 2:
GESTION DES THREADS: TERMINAISON
int main()
{
int i;
pthread_t thA, thB;
printf("Creation du thread An");
pthread_create(&thA, NULL, threadA, NULL);
printf("Creation du thread Bn");
pthread_create(&thB, NULL, threadB, NULL);
usleep(1000000);
//attendre que les threads aient termine
printf("Le thread principal attend que les autres se terminentn");
pthread_join(thA,NULL);
pthread_join(thB,NULL);
exit(0);
}
81. 81
Exemple 2 (suite):
GESTION DES THREADS: TERMINAISON
void afficher(int n, char lettre)
{
int j;
for (j=1; j<n; j++)
{
usleep(1000000);
printf("%c",lettre);
}
}
void *threadA(void *inutilise)
{
afficher(100,'A' );
printf("n Fin du thread An");
pthread_exit(NULL);
}
82. 82
Exemple 2 (suite):
GESTION DES THREADS: TERMINAISON
void *threadC(void *inutilise)
{
afficher(150,'C' );
printf("n Fin du thread
Cn");
pthread_exit(NULL);
}
void *threadB(void *inutilise)
{
pthread_t thC;
printf("Creation du thread Cn");
pthread_create(&thC, NULL, threadC,
NULL);
afficher(100,'B' );
printf("n Le thread B attend la fin du
thread Cn");
pthread_join(thC,NULL);
printf("n Fin du thread Bn");
pthread_exit(NULL);
}
83. 83
Exemple 2 (suite):
GESTION DES THREADS: TERMINAISON
84. 84
Exemple 2 (suite):
GESTION DES THREADS: TERMINAISON
85. 85
Forcer la non-attente d'un thread : Il peut arriver que dans une
application multitâche, on n'ait pas besoin que le processus (le thread
principal) attende la fin d'exécution d’un thread annexe avant de se
terminer. Pour cela, on force le thread annexe à être détaché de son
processus.
GESTION DES THREADS: TERMINAISON
Lors de la création Par appel à la fonction
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PT
HREAD_CREATE_DETACHED);
pthread_create (tid, &attr, func, NULL);
int pthread_detach(pthread_t
thd_id);
86. 86
Thread joignable versus détaché
GESTION DES THREADS: TERMINAISON
Thread Joignable Détaché
Valeur de l’attribut
detachstate (int)
PTHREAD_CREATE_JOI
NABLE (par défaut)
PTHREAD_CREATE_D
ETACHED
Lorsque le thread
…….. se termine
(suite à un appel
pthread_exit)
les valeurs de son
identité et de retour sont
conservées jusqu'à ce qu'un
autre thread
en prenne connaissance
(appel à pthread_join). Les
ressources sont ensuite
libérées.
Aucun autre thread ne
peut les récupérer et les
ressources sont libérées.
87. 87
int pthread_cancel(pthread_t thd_id)
Demande au thread thd_id de se terminer (Pas forcément pris en compte
immédiatement).
Cette requête n’est prise en compte par thd_id que lorsque ce dernier
arrive sur une primitive bloquante (pause, pthread_cond_wait, ….), ou
explicitement via l’appel à pthread_testcancel;
void pthread_testcancel(void);
Le thread courant teste s'il a reçu une demande d'annulation
Le thread se termine à ce point si le test est positif
Le retour du thread vaut PTHREAD_CANCELED
GESTION DES THREADS: ANNULATION
88. 88
int pthread_setcancelstate(int state, int * oldState);
Change l‘état d'annulation du thread courant à state
PTHREAD_CANCEL_ENABLE: annulations autorisées (par
défaut)
PTHREAD_CANCEL_DISABLE: annulations ignorées
Indique l'ancien état si oldState est non nul
Retour : 0 si ok, non nul si erreur
GESTION DES THREADS: ANNULATION
89. 89
int pthread_setcanceltype(int type,int * oldType);
Change le type d'annulation du thread courant à type
PTHREAD_CANCEL_DEFERRED : annulation prise en
compte aux points d'annulation (par défaut)
PTHREAD_CANCEL_ASYNCHRONOUS : annulation prise
en compte immédiatement (dangereux !)
Indique l'ancien type si oldType est non nul
Retour : 0 si ok, non nul si erreur
GESTION DES THREADS: ANNULATION
91. Ordonnancement des processus (lourdslégers)
Ordonnancement des pthreads
91
PLAN DE LA PARTIE II: ORDONNANCEMENT
92. Ordonnancement des processus
Définition
Files d’attentes de l’ordonnancement
L’ordonnanceur
Critères d’ordonnancement
Stratégies d'ordonnancement
Algorithmes d’ordonnancement
Cas d’Etude
Ordonnancement des pthreads
92
PLAN DE LA PARTIE II: ORDONNANCEMENT
93. 93
L’ordonnancement (scheduling) est un ensemble de règles
définissant l'ordre d'exécution des processus en tenant compte
de la disponibilité des ressources nécessaires (processeurs), de
manière à optimiser un ou plusieurs critères.
On peut dire, également, que l'ordonnancement consiste à
allouer une ou plusieurs tranches de temps processeur à
chaque processus existant dans le système.
Dans cette section, on utilise le terme « processus » pour
désigner un processus lourd et/ou un processus léger
(thread).
DÉFINITION
94. 94
Pour gérer les processus durant leur séjour, le SE
maintient plusieurs files d’attente :
Files d’attente des processus prêts : peuvent être représentées par
une ou plusieurs files : une file par classe de processus (processus
système, processus temps réel, processus temps partagé) ou une file
par priorité.
Files d’attente des processus bloqués : peuvent être présentées par
plusieurs files: une file par événement, signal ou ressource attendu
(file des processus en attente de l'imprimante, file des processus en
attente de fin d'E/S sur le disque,...).
FILES D’ATTENTES DE L’ORDONNANCEMENT
95. 95
Un nouveau processus est initialement placé dans la file
d’attente des processus prêts. Il attend dans cette file
jusqu’à ce qu’il soit sélectionné pour son exécution et
qu’on lui accorde le processeur.
Une fois qu’on a alloué le processeur au processus et que
celui-ci est en cours d’exécution, il pourrait se produire
l’un des événements suivants :
FILES D’ATTENTES DE L’ORDONNANCEMENT
96. 96
Le processus pourrait se terminer.
Le processus pourrait consommer le temps qui a été alloué par le
processeur (système à temps partagé). Dans ce cas, le processus
est remis dans la file d’attente des processus prêts.
Le processus pourrait attendre un évènement (signal) arrivant
d’un autre processus.
Le processus pourrait émettre une requête d’E/S et ensuite placé
dans une file d’attente d’E/S.
FILES D’ATTENTES DE L’ORDONNANCEMENT
97. 97
Les différents états de transition du processus entre les
files d’attente sont résumés comme suit:
FILES D’ATTENTES DE L’ORDONNANCEMENT
Files d’attente des
processus prêts
File d’attente des
E/S
File d’attente du
signal
Files d’attente des processus
Processeur
E/S
Arrivé
du signal
Fin d’exécution
Expiration du temps alloué
Requête d’E/S
Attente d’un
évènement
98. 98
L’ordonnanceur (scheduler) est un programme du SE qui
s’occupe de choisir, selon une politique d’ordonnancement
donnée, un processus parmi les processus prêts pour lui
affecter le processeur.
Les principaux objectifs assignés à un ordonnanceur sont:
Occupation maximale du processeur,
S'assurer que chaque processus en attente d'exécution reçoive sa
part de temps processeur.
Minimiser le temps de réponse pour les utilisateurs en mode
interactif,
Satisfaire le maximum de processus des utilisateurs en
respectant certaines contraintes telles que la priorité, l'échéance
(dans les systèmes temps réel), etc…
ORDONNANCEUR
99. 99
Les divers algorithmes d’ordonnancement du processeur
possèdent des propriétés différentes et peuvent favoriser une
classe de processus plutôt qu’une autre.
Pour choisir quel algorithme utiliser dans une situation
particulière, nous devons tenir compte des propriétés des divers
algorithmes.
Plusieurs critères ont été proposés pour comparer et évaluer les
performances des algorithmes d’ordonnancement du
processeur. Les critères les plus souvent utilisés sont :
CRITÈRES D’ORDONNANCEMENT
100. 100
Les critères les plus souvent utilisés sont :
Le taux d'utilisation du processeur : qui est défini par le rapport
temps CPU consommé sur le temps de séjour des processus. Le
taux d'utilisation du processeur doit être le plus élevé possible.
Capacité de traitement : est la quantité de processus terminés par
unité de temps.
Temps de résidence : est le temps passé par le processus dans le
système. C'est la somme du temps d'exécution et du temps passé
dans les différentes files (file des processus prêts, files des
processus bloqués). Soient te: le temps (ou date) d'entrée
processus dans le système et ts: le temps (ou date) de sortie du
processus.
Temps de résidence = ts - te
CRITÈRES D’ORDONNANCEMENT
101. 101
Les critères les plus souvent utilisés sont :
Temps d’attente : est le temps passé à attendre dans la file
d’attente des processus prêts, c'est-à-dire le temps total
d’attente du processeur central
Temps de réponse : est le temps passé dans la file d’attente
des processus prêts avant la première exécution. Soient :
te: le temps (ou date) de soumission de la requête et ts: le
temps (ou date) de début de la réponse à cette requête.
Temps de réponse = ts – te
CRITÈRES D’ORDONNANCEMENT
102. 102
On peut classer les politiques ou stratégies d'ordonnancement
en deux classes:
Non-préemptif (Sans réquisition) : L'exécution du processus en cours
ne peut jamais être interrompue au profit d'un autre processus. Ce
sont les algorithmes utilisés dans les premiers systèmes BATCH.
Préemptif (Avec réquisition) : L'exécution du processus en cours peut
être interrompue au profit d'un autre processus plus prioritaire (ou
plus urgent) ou de même priorité. Ce type d'algorithmes favorise les
processus courts et assure, dans les systèmes interactifs, un temps de
réponse assez bref.
STRATÉGIES D‘ORDONNANCEMENT
103. 103
L’algorithme du Premier Arrivé Premier Servi
(FCFS) :
FCFS (First Come First Served) est l’algorithme le plus
simple qui permet d’allouer le processeur au premier
processus qui le demande.
L’implémentation de la politique FCFS est facilement gérée
avec une file d’attente FIFO. Quand un processus entre
dans la file d’attente des processus prêts, son bloc de
contrôle (PCB ou TCB) est enchaînée à la queue de la file
d’attente. Quand le processeur devient libre, il est alloué au
processus en tête de la file d’attente.
ALGORITHMES D‘ORDONNANCEMENT
104. 104
L’algorithme du Premier Arrivé Premier Servi
(FCFS) :
Exemple : Trois processus P1, P2 et P3 arrivent dans cet
ordre au système. Leurs durées d’exécution sont
respectivement : 24, 3, 3 unités de temps. Calculer le temps
moyen d’attente.
ALGORITHMES D‘ORDONNANCEMENT
105. 105
L’algorithme du Premier Arrivé Premier Servi
(FCFS) :
Exemple :
Le temps d’attente est égal à 0 pour le processus P1, 24
pour le processus P2 et 27 pour le processus P3. Le temps
d’attente moyen est égal à : (0+24+27)/3, soit 17 unités de
temps.
ALGORITHMES D‘ORDONNANCEMENT
106. 106
L’algorithme du Premier Arrivé Premier Servi (FCFS) :
Exemple : Si les processus étaient arrivés dans l’ordre P2, P3 et
P1, les résultats seraient différents :
Le temps moyen d’attente serait : (0+3+6)/3=3 unités.
Ainsi le temps moyen d’attente avec une politique FCFS n’est
généralement pas minimal et peut varier substantiellement si les
durées d’exécution des processus varient beaucoup.
ALGORITHMES D‘ORDONNANCEMENT
107. 107
L’algorithme du Premier Arrivé Premier Servi (FCFS) :
L’algorithme FCFS tend à pénaliser les travaux courts : il n’effectue
pas de réquisition; c’est à dire qu’une fois que le processeur a été
alloué à un processus, celui-ci le réquisitionne jusqu’à ce qu’il
termine ou qu’il se bloque (attente d’un évènement ou d’E/S).
L’algorithme FCFS n’est pas recommandé pour les systèmes à temps
partagé, où il est important que l’utilisateur obtienne le processeur à
des intervalles réguliers. Il peut paraître désastreux de permettre
qu’un processus garde le processeur pendant une période étendue.
ALGORITHMES D‘ORDONNANCEMENT
108. 108
L’algorithme du Plus Court d’abord (SJF):
L’algorithme SJF (Shortest Job First) affecte le
processeur au processus possédant le temps
d’exécution le plus court. Si plusieurs processus ont la
même durée, une politique FIFO sera alors utilisée
pour les départager.
ALGORITHMES D‘ORDONNANCEMENT
109. 109
L’algorithme du Plus Court d’abord (SJF):
Exemple: On soumet au système quatre processus P1, P2, P3
et P4 dont les durées d’exécution sont données par le tableau
suivant :
Le temps moyen d’attente est = (0+3+9+16)/4=7. Alors que si on avait choisi une
politique FCFS, le temps moyen serait de : 10.25 unités de temps.
ALGORITHMES D‘ORDONNANCEMENT
110. 110
L’algorithme du Plus Court d’abord (SJF):
Il a été prouvé que l’algorithme SJF est optimal dans le temps
dans le sens qu’il obtient le temps d’attente le plus court pour
un ensemble de processus donné. Toutefois, cet algorithme est
difficile à implémenter pour une raison simple : Comment
peut-on connaître le temps d’exécution d’un processus à
l’avance ?.
ALGORITHMES D‘ORDONNANCEMENT
111. 111
L’algorithme d’ordonnancement avec priorité
Cet algorithme associe à chaque processus une priorité, et le
processeur sera affecté au processus de plus haute priorité.
L'exécution du processus en cours peut être interrompue au profit
d'un autre processus plus prioritaire (c’est un algorithme
préemptif ou avec réquisition).
Les priorités des processus peuvent être définies en fonction de
plusieurs paramètres : le type de processus, les limites de temps,
les limites mémoires, …etc.
ALGORITHMES D‘ORDONNANCEMENT
112. 112
L’algorithme d’ordonnancement avec priorité
Exemple : On dispose de 5 processus ayant des priorités différentes
(les priorités varient de 0 à 255; (0 la plus faible priorité et 255 la
plus forte priorité), comme le montre ce tableau :
Le temps moyen d’attente est = (0+1+6+16+18)/5=8.2 unités de temps.
ALGORITHMES D‘ORDONNANCEMENT
113. 113
L’algorithme d’ordonnancement avec priorité
Une situation de blocage (famine) peut survenir si les processus de
basse priorité attendent indéfiniment le processeur, alors que des
processus de haute priorité continuent à affluer.
Pour éviter une telle situation, on peut utiliser la technique dite du
vieillissement. Elle consiste à incrémenter graduellement la priorité
des processus attendant dans le système pendant longtemps. Par
exemple, nous pourrions incrémenter de 1 la priorité d’un processus en attente
toutes les 15 minutes. En fin de compte, même un processus ayant une priorité
initiale égale à 0 aurait la plus haute priorité dans le système et serait exécuté.
ALGORITHMES D‘ORDONNANCEMENT
114. 114
L’algorithme du Tourniquet (Round Robin)
Cet algorithme a été conçu pour des systèmes à temps partagé. Il
alloue le processeur aux processus à tour de rôle, pendant une
tranche de temps appelée quantum.
Dans la pratique le quantum s’étale entre 10 et 100 ms.
Exemple : On dispose de 3 processus P1, P2 et P3 ayant comme
durée d’exécution, respectivement 24, 3 et 3 ms. Calculer le
temps moyen d’attente en utilisant un algorithme Round Robin,
avec un quantum de 4 ms.
ALGORITHMES D‘ORDONNANCEMENT
115. 115
L’algorithme du Tourniquet (Round Robin)
Exemple : On dispose de 3 processus P1, P2 et P3 ayant comme
durée d’exécution, respectivement 24, 3 et 3 ms. Calculer le
temps moyen d’attente en utilisant un algorithme Round Robin,
avec un quantum de 4 ms.
Le temps moyen d’attente est de : (6+4+7)/3 = 17/3 = 5.66 ms
ALGORITHMES D‘ORDONNANCEMENT
116. 116
L’algorithme du Tourniquet (Round Robin)
La performance de l’algorithme de Round Robin dépend
largement de la taille du quantum. Si le quantum est très grand ,
la politique Round Robin serait similaire à celle du FCFS. Si le
quantum est très petit, la méthode Round Robin permettrait un
partage du processeur : Chacun des utilisateurs aurait
l’impression de disposer de son propre processeur .
Cependant le quantum doit être choisi de sorte à ne pas
surcharger le système par de fréquentes commutations de
contexte.
ALGORITHMES D‘ORDONNANCEMENT
117. 117
L’algorithme du Tourniquet (Round Robin)
Exemple : On dispose d’un processus P dont le temps d’exécution
est de 10 ms. Calculer le nombre de commutations de contexte
nécessaires pour un quantum égal respectivement à : 12, 6 et 1.
ALGORITHMES D‘ORDONNANCEMENT
10
118. 118
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
Une autre classe d’algorithmes d’ordonnancement a été développée
pour des situations où on peut facilement classer les processus dans
des groupes différents.
Exemple 1: on peut diviser les processus en deux classes: les
processus de premier plan (interactifs) et les processus d’arrière plan
qui possèdent des besoins différents en ce qui concerne le temps de
réponse et ils pourraient donc devoir être ordonnancé différemment.
De plus, les processus de premier plan peuvent être prioritaires par
rapport aux processus d’arrière plan.
ALGORITHMES D‘ORDONNANCEMENT
119. 119
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
Une autre classe d’algorithmes d’ordonnancement a été
développée pour des situations où on peut facilement classer les
processus dans des groupes différents.
Exemple 2: comme, on peut aussi diviser les processus en quatre
classes (des processus les plus prioritaires aux processus les
moins prioritaires): les processus systèmes, interactifs, batch et
utilisateurs.
ALGORITHMES D‘ORDONNANCEMENT
120. 120
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
Cet algorithme découpe la file d’attente des processus prêts en
plusieurs files d’attentes séparées.
Exemple 1: Exemple 2:
ALGORITHMES D‘ORDONNANCEMENT
Processus du premier plan
Processus d’arrière plan
Processus Système
Processus Interactifs
Processus Batch
Processus Utilisateurs
priorité
121. 121
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
Les processus sont en permanence assignés à une file d’attente en se
basant généralement sur certaines propriétés du processus, comme :
le type de processus, la taille de la mémoire, la priorité, … etc.
Chaque file d’attente possède son propre algorithme
d’ordonnancement.
Exemple 2: la file d’attente des processus systèmes est ordonnancée
selon algorithme de plus haute priorité, celle des processus
interactifs est gérée selon l’algorithme Round Robin et la file des
processus batch est gérée selon l’algorithme FCFS.
ALGORITHMES D‘ORDONNANCEMENT
122. 122
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
D’autre part, il doit y avoir un ordonnancement entre les files
d’attente elles-mêmes.
Cas 1: Chaque file d’attente est absolument prioritaire par rapport
aux files d’attente de niveau inférieur.
Exemple 2: aucun processus de la file d’attente des processus batch
ne pourra s’exécuter à moins les files d’attente des processus
système et interactifs ne soient toutes vides. De plus, si un processus
interactif arrive au système, alors qu’un processus batch est en train
de s’exécuter, celui-ci doit être interrompu.
ALGORITHMES D‘ORDONNANCEMENT
123. 123
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
D’autre part, il doit y avoir un ordonnancement entre les files
d’attente elles-mêmes.
Cas 2: Affecter des tranches de temps aux files d’attente.
Chaque file d’attente obtient une certaine partie du temps
processeur, lequel doit s’ordonnancer entre les différents
processus qui la composent.
Exemple 1: on peut attribuer 80% du temps processeur à la
file d’attente des processus de premier plan et 20% pour la
file d’attente des processus d’arrière plan.
ALGORITHMES D‘ORDONNANCEMENT
124. 124
L’algorithme d’ordonnancement avec files d’attente
multiniveaux
Normalement, dans un algorithme avec des files d’attente
multiniveaux, les processus sont assignés en permanence à une
file d’attente dès qu’ils rentrent dans le système. Les processus
ne se déplacent pas entre les files d’attente. Cette organisation
possède l’avantage d’une basse surcharge due à
l’ordonnancement, mais elle manque de souplesse.
ALGORITHMES D‘ORDONNANCEMENT
125. 125
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Dans l’algorithme précédent, un processus ne change pas de file
tout le long de son exécution. Avec cet algorithme (appelé aussi
avec plusieurs niveaux dépendants), un processus peut basculer
entre des files. Ceci est réalisé dans le but d'isoler les processus
longs d'une part, et de relancer les processus de faible priorité
d'autre part.
ALGORITHMES D‘ORDONNANCEMENT
126. 126
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Cet algorithme utilise N files d’attente avec des règles suivantes:
Un processus qui entre dans le système est mis dans la première file.
Après avoir reçu une tranche de temps, il est mis dans la deuxième
file.
Après chaque tranche reçue, il passe dans la file suivante.
L’algorithme choisit le premier processus de la première file non
vide.
ALGORITHMES D‘ORDONNANCEMENT
127. 127
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Cette stratégie est définie par les paramètres suivants:
le nombre de files.
l'algorithme de l’ordonnancement de chaque file.
une méthode de transition d'un processus d'une file à une autre.
une méthode qui choisit la file à recevoir un nouveau processus.
Elle permet de favoriser les petits travaux, sans avoir besoin de
savoir à l’avance combien de temps CPU ceux-ci vont utiliser.
ALGORITHMES D‘ORDONNANCEMENT
128. 128
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Exemple : Un système est doté de 3 files d’attentes
mutiniveaux :
ALGORITHMES D‘ORDONNANCEMENT
129. 129
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Exemple : Un système est doté de 3 files d’attentes
mutiniveaux :
Un processus entrant dans le système sera rangé dans la file 0. On
donne une tranche de temps de 8 ms au processus. S’il ne finit pas,
il est déplacé vers la file1. Si la file 0 est vide, on donne une tranche
de temps de 16 ms au processus en tête de la file 1. S’il ne termine
pas, il est interrompu et il est mis dans la file 2. Les processus de la
file 2 sont exécutées seulement quand les files 0 et 1 sont vides.
ALGORITHMES D‘ORDONNANCEMENT
130. 130
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Exemple : L’algorithme avec quantum variable
Pour éviter qu'il y ait beaucoup de commutations pour les
processus longs, il est préférable d'allouer un plus grand quantum
à ces processus. Lorsqu'un processus passe à l'état élu : Pour la
première fois, le processeur lui est alloué pendant un quantum.
Pour la seconde fois, le processeur lui est alloué pendant 2
quantum... Pour la nième fois, le processeur lui est alloué pendant
2(n-1) quantum.
ALGORITHMES D‘ORDONNANCEMENT
131. 131
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Exemple : L’algorithme avec quantum variable
Chaque processus a une priorité. Cette dernière dépend du nombre
de quantum qui lui sera alloué lors de sa prochaine activation. Les
processus dont le nombre de quantum est le plus petit sont les plus
prioritaires. Les processus prêts sont répartis selon leur priorité dans
des files (FIFO). D'abord on fait l'élection du processus le plus
prioritaire qui se trouve en tête de file. Lorsque l'exécution d'un
processus est suspendue pour la nième fois, sa priorité est recalculée 2n
puis il est inséré à la queue de la file appropriée.
ALGORITHMES D‘ORDONNANCEMENT
132. 132
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Exemple : L’algorithme avec quantum variable
Considérons un processus qui doit effectuer des calculs pendant
100 quantum. Ce processus obtient successivement 1, 2, 4, 8, 16,
32 et 64 quantum. Mais il utilisera 37 des 64 derniers quantum.
Le nombre de changements de contexte passe de 100 (cas du
tourniquet) à 7. Le processeur passe moins de temps à commuter
et a donc un meilleur temps de réponse.
ALGORITHMES D‘ORDONNANCEMENT
133. 133
L’algorithme d’ordonnancement avec files d’attente
multiniveaux rétroactives
Exemple : L’algorithme avec quantum variable
Un processus qui descend de plus en plus dans les files à priorité
s'exécute de moins en moins fréquemment et favorise ainsi les
processus courts en mode interactif. Pour ne pas défavoriser un
processus qui s'était exécuté pendant assez longtemps avant de
devenir interactif, on peut lui attribuer la plus haute priorité dès
qu'un retour chariot est tapé sur le terminal associé au processus
(les premières versions d'Unix utilisaient cette solution).
ALGORITHMES D‘ORDONNANCEMENT
135. 135
MS-DOS
MS-DOS est un système mono-utilisateur et mono-
tâche. Il peut y avoir, à un moment donné, plusieurs
processus en mémoire mais un seul est à l'état prêt,
tous les autres étant en attente de la fin d'un fils.
L'ordonnanceur des processus du système MS-DOS est
très simple : il exécute un processus jusqu'à ce qu'il se
termine ou crée un fils. Le processus créateur est
suspendu jusqu'à ce que le processus créé se termine.
CAS D’ETUDE
136. 136
WINDOWS
L'algorithme d'ordonnancement est un algorithme préemptif à
priorités dynamiques avec files d’attentes multi-niveaux
Windows ordonne des threads, sans se préoccuper de savoir à
quel processus ils appartiennent.
La priorité d’un processus (donc la priorité de tous ses threads)
peut être fixée à (en ordre décroissant de priorité) : realtime, high,
above normal, normal, below normal ou idle.
De plus, la priorité d'un thread par rapport aux autres du même
processus peut être définie parmi l’ensemble des valeurs
suivantes: time critical, highest, above normal, normal, below
normal, lowest ou idle.
CAS D’ETUDE
137. 137
WINDOWS
Selon la combinaison de ces deux priorités (processus +
thread), un thread est attribué une valeur de priorité
entre 0 et 31, appelé priorité de base.
Cette priorité peut changer au cours de l'exécution du
thread. On parle de la priorité courante de thread
qui est considérée pour l'ordonnancement.
CAS D’ETUDE
138. 138
WINDOWS
La priorité courante d'un thread peut être augmentée
dans certaines circonstances :
Le thread vient d'être libéré d'une attente d'entrée/sortie (ex. +1
pour disque, +6 pour clavier, +8 pour carte son)
Le thread vient d'être libéré d'une attente sur un sémaphore (+2
pour thread d'un processus en premier plan et +1 pour les autres)
À chaque valeur de priorité, une file d'attente est
associée et Windows parcourt ces files de manière
classique. Chaque file est traitée par l'algorithme du
tourniquet (quantum variable).
CAS D’ETUDE
139. 139
WINDOWS
Lorsqu'un thread a expiré son quantum, sa priorité
courante descend de 1 jusqu'à ce qu'il revienne à sa
priorité de base.
Quand un thread n'a pas été exécuté depuis un temps
qui dépasse un seuil défini, il passe à la priorité 15
pour deux quanta
–Finalement, un thread associé à une fenêtre qui vient
d'être activée reçoit un plus gros quantum
(typiquement 3 X quantum normal).
CAS D’ETUDE
140. 140
UNIX
C’est un ordonnanceur à plusieurs files multiniveaux;
Les processus prêts sont répartis dans les files selon
leur priorité. Les priorités des processus s'exécutant en
mode utilisateur sont positives ou nulles, alors que
celles des processus s'exécutant en mode noyau sont
négatives.
CAS D’ETUDE
141. 141
CAS D’ETUDE
UNIX
Les priorités des processus s'exécutant en mode
utilisateur sont positives ou nulles, alors que celles des
processus s'exécutant en mode noyau sont négatives.
142. 142
CAS D’ETUDE
UNIX
L'ordonnanceur choisit le processus le plus prioritaire
qui se trouve en tête de file. Le processus élu est alors
exécuté pendant au maximum un quantum (100 ms).
S'il ne se termine pas ou ne se bloque pas au bout de ce
quantum, il est suspendu. Le processus suspendu est
inséré en queue de sa file.
La priorité initiale d'un processus utilisateur est en
général égal à zéro.
143. 143
CAS D’ETUDE
UNIX
Les priorités des processus prêts sont recalculées
périodiquement (toutes les secondes) en ajoutant à sa
valeur de base, la valeur suivante: (cpu/2 + k) ; où
cpu le temps récent (en nombre de top d'horloge) utilisé
k est une constante connue par le système.
Lorsqu'un processus passe de l'état bloqué à l'état prêt,
il se voit attribuer une forte priorité (négative). Après
le calcul des priorités, les processus sont déplacés vers
les files d'attente correspondant à leurs nouvelles
priorités.
144. 144
CAS D’ETUDE
LINUX
Linux offre trois politiques d'ordonnancement:
SCHED_FIFO, SCHED_RR et SCHED_OTHER.
A sa création, chaque processus se voit attribuer une
politique d'ordonnancement. Il possède aussi une
valeur de priorité, appelée priorité statique.
La valeur de priorité varie de 1 à 40 ( 1 plus faible et
40 la plus forte).
Par défaut, un processus utilisateur a une valeur de
priorité de 20.
145. 145
CAS D’ETUDE
LINUX
SCHED_FIFO, garantit au processus une utilisation
illimitée du processeur. Il ne sera interrompu que dans
une des circonstances suivantes :
–Le processus se bloque sur un appel système ou se
termine.
–Un autre processus de la classe SCHED_FIFO de
priorité plus élevée est prêt.
Le processus libère lui-même le processeur, en
exécutant l'appel système sched_yield().
146. 146
CAS D’ETUDE
LINUX
SCHED_RR est un algorithme de tourniquet où
chaque processus de cette classe se voit attribuer un
quantum. Il sera interrompu dans une des
circonstances suivantes :
–Le quantum de processus est écoulé.
Le processus se bloque sur un appel système ou se termine.
–Un autre processus de la classe SCHED_RR de priorité plus
élevée est prêt.
Un autre processus de la classe SCHED_FIFO est prêt
Le processus exécute l'appel système sched_yield().
147. 147
CAS D’ETUDE
LINUX
SCHED_OTHER est un algorithme de tourniquet où
chaque processus de cette classe se voit attribuer un
quantum. Il sera interrompu dans une des
circonstances suivantes :
–Le quantum de processus est écoulé.
Le processus se bloque sur un appel système ou se termine.
Un autre processus de la classe SCHED_FIFO ou SCHED_RR
est prêt
Le processus exécute l'appel système sched_yield().
148. 148
CAS D’ETUDE
LINUX
Le quantum attribué à un processus de la classe
SCHED_RR ou SCHED_OTHER est variable et établi
selon les principes suivants:
1. La valeur initiale du quantum est égale à la valeur de
priorité. Ainsi, un processus de priorité 25 aura un quantum
de 25 unités de temps (= 10ms), ce qui correspond à 250 ms.
2. À chaque unité de temps (10 ms), on diminue d’unité la
valeur du quantum du processus en cours d'exécution dans
le processeur.
149. 149
CAS D’ETUDE
LINUX
3. Éventuellement, on peut arriver à une situation où tous les
processus de la classe SCHED_OTHER sont dans une des deux
situations suivantes :
–Son quantum est 0. Il a écoulé tout le temps qui lui était
alloué.
–Il est bloqué. Il n'a pas nécessairement épuisé son quantum.
Dans ce cas, tous les quanta (y compris les quanta des processus
en attente qui ont encore une valeur non nulle) sont réajustés
selon la formule suivante :
Quantum = Quantum/2 + priorité
150. 150
CAS D’ETUDE
LINUX
Dans ce cas, tous les quanta (y compris les quanta des processus
en attente qui ont encore une valeur non nulle) sont réajustés
selon la formule suivante :
Quantum = Quantum/2 + priorité
Ceci a pour effet de favoriser les processus qui n'ont pas utilisé
tout le temps qui leur est alloué. En effet, un processus qui n'a
pas épuisé son quantum se retrouve avec une nouveau
quantum plus élevé que l'ancien.
151. 151
CAS D’ETUDE
LINUX
Dans ce cas, tous les quanta (y compris les quanta des processus
en attente qui ont encore une valeur non nulle) sont réajustés
selon la formule suivante :
Quantum = Quantum/2 + priorité
Ceci est appliqué aussi sur les processus de la classe SCHED_RR
de même priorité. Par exemple, si deux processus avec priorité
20 s'exécutent, ils alterneront dans le processeur. Si
entretemps apparaît un processus de la même classe, mais de
priorité 25, c'est ce dernier qui prend le contrôle du processeur
et ne le redonnera que lorsqu'il se terminera ou il se bloquera
par un appel ou un processus plus prioritaire.
152. 152
CAS D’ETUDE
LINUX
Lorsque l'ordonnanceur est appelé, Linux attribue une
note à chaque processus en utilisant la méthode
suivante :
153. 153
CAS D’ETUDE
LINUX
Cette note dépend à la fois de la priorité du processus
et de la valeur actuelle de son quantum. C'est cette
note qui permettra de déterminer quel processus
prendra le contrôle du processeur.
154. 154
CAS D’ETUDE
LINUX
Exemple: Soient les processus suivants. Donner
l’ordre d’exécution des processus (diagramme de
Gantt)
Processus A B C
Priorité statique 20 18 10
Politique
d’ordonnancement
SCHED_OTHER SCHED_OTHER SCHED_OTHER
Instant d’arrivé 0 0 0
Historique
temporelle
CPU: 16 ut, E/S:
16 ut; CPU: 25
CPU: 4 ut, E/S: 11
ut; CPU: 30
CPU: 25
155. 155
CAS D’ETUDE
LINUX
Exemple:
Initialement, c'est le processus A qui a la meilleure note.
C'est donc lui qui est exécuté, ayant droit à 20 ut.
Le processus A s'interrompt après 16 ut pour exécuter une
E/S (appel système bloquant). L’ordonnanceur choisit le
processus B.
Le processus B s'exécute pendant 40 ms (lui aussi se bloque
sur une E/S). À ce moment, le processus C prend le contrôle
et utilise toutes le 100 ms qui lui sont accordées.
156. 156
CAS D’ETUDE
LINUX
Exemple:
On se retrouve alors dans la situation suivante : A et B sont
toujours bloqués, et C a un quantum nul. Le système
réalisera donc un réajustement des quanta. Les processus
se verront attribuer les nouvelles valeurs suivantes
(rappelons qu'il reste 40 ms à A et 140 ms à B) :
157. 157
CAS D’ETUDE
LINUX
Exemple:
Comme A et B sont toujours bloqués, C s'exécute à
nouveau. Entre temps A et B redeviennent prêts durant ce
temps.
Après 100 ms, C a épuisé son quantum. Il aura une note
égale à zéro. Le système choisira alors entre A et B. Voici
les notes qui sont attribuées aux processus :
158. 158
CAS D’ETUDE
LINUX
Exemple:
C'est donc le processus B qui sera choisi, malgré sa priorité
statique plus basse. Il est favorisé parce qu'il a utilisé une
proportion plus petite du temps qui lui avait été alloué.
Après 25 ut, le processus A sera choisi. Il écoule son
quantum qui vaut 22 ut.
On se retrouve alors dans la situation suivante : A, B, C ont
tous un quantum nul. Le système réalisera donc un
réajustement des quanta……et on se trouve à l’état initial
où le processus A a la meilleur note.
159. Ordonnancement des processus (lourds et ou légers)
Ordonnancement des pthreads
Principe
Exemple
Portée
Domaines d’allocation
Attributs (héritage, portée, politique et priorité)
Configuration du mode d’ordonnancement
Relâchement du processeur par un thread
159
PLAN DE LA PARTIE II: ORDONNANCEMENT
160. 160
La norme POSIX effectue l’ordonnancement à l’aide d’un
algorithme préemptif (réquisition) à priorités fixes.
Il y au moins 32 niveaux de priorité, de 0 à 31 (0 la plus faible
priorité et 31 la plus forte priorité)
A tout instant, un thread moins prioritaire peut être
interrompu par un autre thread plus prioritaire que lui.
A chaque instant, l’ordonnanceur choisi le thread le plus
prioritaire.
Qu'est-ce qui se passe si deux threads ont la même
priorité?
PRINCIPE
161. 161
Il y a une file d'attente par niveau de priorité, contenant
tous les threads prêts ayants cette priorité
PRINCIPE
162. 162
Il y a une file d'attente par niveau de priorité, contenant
tous les threads prêts ayants cette priorité
Le thread prêt de plus haute priorité est dans la file d'attente
non vide de plus haut niveau
Le premier thread de la file d'attente non vide de plus haut
niveau est sélectionné et devient le thread en exécution (actif)
Le thread interrompu par un thread plus prioritaire, est inséré
en tête de la file correspondant à sa priorité.
Donc, la question est comment sont traitées les threads
de même priorité (i.e de la même file d'attente)?
PRINCIPE
163. 163
Les threads de même priorité peuvent être traitées selon
deux politiques:
SCHED_FIFO : First In First Out queueing. Cela signifie
que le thread est prévue jusqu'à ce qu’il se termine, est annulé
par un autre thread, s’est bloqué à la demande d’E/S par
exemple ou est interrompu par un thread plus prioritaire.
SCHED_RR: Round Robin queueing. Le thread est
également prévue jusqu’à ce que son quantum
d’ordonnancement expire. Il sera inséré à la queue de sa file.
PRINCIPE
164. 164
La norme POSIX propose une troisième politique,
appelée SCHED_OTHER qui dépend de
l'implémentation de l’ordonnanceur du S.E.
Souvent, il s’agit d’un algorithme classique temps
partagé: Tous les threads sont dans le même tourniquet, il
n’y a pas de niveau de priorité.
Ceci permet l’absence de situation de famine (les threads
de bas priorité attendent indéfiniment) qui peut être
engendrée avec la politique SCHED_FIFO ou
SCHED_RR.
PRINCIPE
166. 166
POSIX ne spécifie pas l’ordonnancement entre les
threads appartenant à des processus différents. C’est
pourquoi, il est nécessaire de spécifier la portée (ou
scope en anglais) de l’activité d’ordonnancement dans
laquelle le thread participe.
En d’autres termes, la portée détermine combien des
threads (et lesquels) un thread donné doit concurrencer
au moment de la sélection (par l’ordonnanceur) pour
s’exécuter sur un CPU libre.
PORTÉE
167. 167
Un Pthread peut être ordonnancé à la portée du
Système (PTHREAD_SCOPE_SYSTEM). Lorsque
l’ordonnancement s’effectue, le thread est sélectionné parmi
l’ensemble des threads du système (des différents processus).
A chaque pthread est associé un thread noyau.
PORTÉE
168. 168
Un Pthread peut être ordonnancé à la portée du
Processus (PTHREAD_SCOPE_PROCESS). Lorsque
l’ordonnancement s’effectue, le thread est sélectionné parmi
l’ensemble des threads du même processus (programme).
Les Pthreads d'un même processus sont prises en charge par
un pool de threads noyau. Un nombre maximum de threads
noyau existent pour un processus.
PORTÉE
169. 169
La discussion de la portée d’ordonnancement devient
compliquer dans des systèmes multiprocesseurs. La plupart
des S.E permettent aux collections de CPU d’être traitées
comme des unités séparées à des fins d’ordonnancement.
DOMAINES D’ALLOCATION
170. 170
La norme Pthreads reconnaît l’existence de ces
groupements que les appelle « domaines d'allocation
d'ordonnancement ». Mais, elle ne définit pas les
politiques et les interfaces qui les concernent.
DOMAINES D’ALLOCATION
171. 171
Quatre attributs d’un pthread sont associés à
l'ordonnancement:
Inheritsched: ordonnancement hérité ou explicit?
Scope: portée de la compétition entre les threads
(processus ou système)
Schedpolicy: politique d’ordonnancement
permettant de gérer les threads de même priorité
(FIFO, RR, OTHER)
Schedparam: priorité du thread permettant de
choisir la/les threads à activer.
ATTRIBUTS
172. 172
Par défaut, un nouveau thread est créé avec les
attributs d'ordonnancement (portée, politique et
priorité) de son créateur.
La valeur par défaut est PTHREAD_INHERIT_SCHED.
Si on veut créer un thread avec des attributs
d’ordonnancement spécifiques, il faut modifier la valeur
de l'attribut de l’héritage à
PTHREAD_EXPLICIT_SCHED en utilisant la
fonction pthread_attr_setinheritsched ().
ATTRIBUT DE L’HÉRITAGE
173. 173
int pthread_attr_getinheritsched (pthread_attr_t*
attr, int* valeur);
int pthread_attr_setinheritsched (pthread_attr_t*
attr, int valeur);
Valeurs possibles:
PTHREAD_INHERIT_SCHED (valeur par défaut):
l’ordonnancement hérité du thread appelant.
PTHREAD_EXPLICIT_SCHED: l’ordonnancement spécifié à
la création du thread
ATTRIBUT DE L’HÉRITAGE
174. 174
int pthread_attr_getscope (const pthread_attr_t * attr,
int* valeur);
int pthread_attr_setscope (const pthread_attr_t * attr, int
valeur);
Valeurs possibles:
PTHREAD_SCOPE_SYSTEM (valeur par défaut): A chaque
Pthread est associé un thread noyau.
PTHREAD_SCOPE_PROCESS : Les Pthreads d'un même
processus sont prises en charge par un pool de threads noyau.
La taille du pool peut être consultée / modifiée par:
int pthread_getconcurrency (void);
int pthread_setconcurrency (int valeur);
ATTRIBUT DE LA PORTÉE
175. 175
int pthread_attr_getschedpolicy (const
pthread_attr_t * attr, int* valeur);
int pthread_attr_setschedpolicy (const
pthread_attr_t * attr, int valeur);
Valeurs possibles:
SCHED_FIFO: Les threads de même priorité sont
ordonnancés en FIFO.
SCHED_RR: Les threads de même priorité sont ordonnancés
en tourniquet.
SCHED_OTHER (valeur par défaut): Tous les threads sont
dans le même tourniquet, il n’y a pas de niveau de priorité.
ATTRIBUT DE LA POLITIQUE
176. 176
int pthread_attr_getschedparam (const
pthread_attr_t * attr, struct schedparam* sched);
int pthread_attr_setschedparam (const
pthread_attr_t * attr, struct schedparam sched);
La structure schedparam possède le champ:
int sched_priority// priorité du thread.
La priorité est une valeur entière comprise entre
sched_get_priority_min (classe) et
sched_get_priority_max (classe)
Classe: SCHED_FIFO, SCHED_RR, SCHED_OTHER
ATTRIBUT DE LA PRIORITÉ
177. 177
L’algorithme d’ordonnancement des pthreads est
contrôlé par trois attributs: scope (portée), policy
(politique) et priority (priorité) pour chaque thread.
Ces attributs sont définis lorsque le thread est créé.
Exemple: Création d’un thread de priorité moyenne
avec la politique FIFO.
CONFIGURATION DU MODE D’ORDONNANCEMENT
179. 179
Cependant, la politique (policy) et la priorité (priority)
peuvent être modifiés alors que le thread est en cours
d’exécution.
int pthread_setschedparam(pthread_t thread, int
policy, const struct sched_param *param);
int pthread_getschedparam(pthread_t thread, int
*policy, struct sched_param *param);
Exemple: Modification dynamique de la priorité et la
politique d’un thread
CONFIGURATION DU MODE D’ORDONNANCEMENT
181. 181
RELÂCHEMENT DU PROCESSEUR PAR UN THREAD
Demande de relâchement du processeur :
int sched_yield (void);
Le thread appelant demande à libérer le processeur.
Il est inséré à la queue de la file d’attente correspondant à sa
priorité.
Il reprendra son exécution lorsque tous les threads de priorité
supérieure ou égale à la sienne se sont exécutées.
S’il est le seul thread le plus prioritaire dans le système, il
continuera à fonctionner après un appel à sched_yield ().
183. Généralités
Exclusion Mutuelle
Sémaphores
Moniteurs
Interblocages
183
PLAN DE LA PARTIE III
184. 184
Un processus a besoin de ressources pour s’exécuter:
procédures et données, mémoires, processeur (UC et
d’autres éventuellement), périphériques, fichiers, ….
On peut classifier les ressources en plusieurs types
possibles selon diverses caractéristiques:
Physiques vs logiques
Locales vs communes
Mono-accès vs multi-accès
Banalisées vs non banalisées
Préemptibles vs non préemptibles
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
185. 185
Ressources physiques vs logiques
Une ressource physique désigne une entité concrète
représentée par un organe physique capable de fournir un
service indispensable à l‘exécution d'un processus (Ex:
processeurs, mémoire, canaux, périphériques).
Une ressource logique désigne une entité abstraite
représentée par un ensemble d'informations ou d'actions à
exécuter indispensable à l‘exécution d'un processus (Ex:
procédure désignée par son nom et ses paramètres, fichier,
table, primitives et outils de synchronisation,...).
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
186. 186
Ressources locales vs communes
Une ressource locale est utilisée uniquement au
niveau du processus (Ex: fichier temporaire, variables
locales du programme,...)
Une ressource commune (ou partageable) peut être
utilisée par plusieurs processus (Ex: disque,
imprimante, fichier en lecture, ….).
Le degré de partageabilité d'une ressource est définie comme
étant le nombre maximum de processus pouvant accéder
simultanément à une ressource.
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
187. 187
Ressources mono-accès vs multi-accès
Une ressource mono-accès (ou critique) est une ressource de
degré de partageabilité 1, c.-à-d. qu'un seul processus au
plus peut y accéder à un instant donné (Ex: imprimante,
fichier accédé en écriture, ….)
Une ressource multi-accès (ou N-partageable) est une
ressource de degré de partageabilité N>1, c.-à-d. que N
processus au plus peuvent y accéder simultanément (Ex:
fichier accédé en lecture « N théoriquement infini »)
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
188. 188
Ressources banalisées vs non banalisées
Une ressource banalisée existe en plusieurs exemplaires
identiques où le choix de l'unité à allouer est sans
importance pour le demandeur (Ex: processeur parmi
plusieurs processeurs identiques, pages mémoire, secteurs
de disque.....)
Une ressource non banalisée n’existe pas en plusieurs
exemplaires identiques, ainsi, sa désignation devra être
explicite (Ex: terminal graphique ou spécifique, processeur
particulier, fichier nommé...)
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
189. 189
Ressources préemptibles vs non préemptibles
Une ressource préemptible désigne toute ressource qu'on
peut retirer à un processus alors qu'il n'a pas fini de
l'utiliser. Cette qualité ne peut être obtenue que si l'état de
la ressource peut être sauvegardé et restauré. (Ex:
Processeur, Mémoire vive, ...)
Une ressource non préemptible désigne toute ressource
qu'on ne peut retirer à un processus tant qu'il ne l' a pas
libérée. (Ex: Imprimante, fichier accédé en écriture, ....)
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
190. 190
De même qu'un processus, une ressource est repérée par un
descripteur (contenant un ensemble d’informations qui
décrivent l’état et l’utilisation de la ressource) et passe par une
série d'états:
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
191. 191
Libre: la ressource est disponible
Demandée: présence d'une demande
Attendue: présence d'une file d'attente de processus demandeurs
Allouée: ressource attribuée à un processus
Libérée: ressource récupérée après utilisation (soit après requête
de libération, soit récupéré par le système en cas de fin anormale)
Requise: si la ressource est préemptible elle sera récupérée avant
fin d'utilisation pour être réattribuée à un autre processus.
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
192. 192
Au niveau du processus demandeur, on ne voit que deux états:
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
193. 193
Le SE garde la liste des descripteurs des ressources dans une
table, appelée table des ressources.
Cette table indique si la ressource est disponible ou non, et, à
quel processus elle est allouée (cas non disponible).
A chaque ressource est associée une file d’attente, pointée
par la table des ressources, contenant les blocs de contrôle des
processus/threads qui l’attendent.
Chaque fois qu’un nouveau processus fait une demande de la
ressource et que cette dernière n’est pas disponible, son
PCB/TCB est ajouté à la file d’attente (selon une politique
d’ordonnancement: FIFO, SJF, priorité, etc).
GÉNÉRALITÉS (RESSOURCES D’UN PROCESSUS)
194. 194
Dans un environnement multitâches, plusieurs processus
peuvent se dérouler simultanément. On parle des
processus parallèles dont leurs exécutions se
chevauchent dans le temps.
Exécution séquentielle stricte des deux processus.
Exécution séquentielle sur un seul processeur pseudo-
parallélisme
Exécution en parallèle sur deux processeurs distincts
parallélisme réel
GÉNÉRALITÉS (PROCESSUS PARALLÈLES)
195. 195
Selon la nature des relations existantes entre les
processus parallèles, on peut distinguer deux types:
Processus disjoints (Indépendants) qui n’ont aucune
relation commune. Leurs exécutions respectives sont
indépendantes et leurs contextes respectifs sont disjoints.
Deux processus P1 et P2 sont disjoints si les exécutions
suivantes sont équivalentes (donnent les mêmes résultats ) : (
P1 II P2 ), ( P1 ; P2 ), (P2 ; P1) .
Dans ce cas, P1 et P2 n’ont aucune interaction (sauf le
processeur en cas de monoprocesseur) ; De plus, l’exécution
parallèle de P1 et P2 permettra d’optimiser le temps total
d’exécution.
GÉNÉRALITÉS (PROCESSUS PARALLÈLES)
196. 196
Selon la nature des relations existantes entre les
processus parallèles, on peut distinguer deux types:
Processus concurrents qui interagissent les uns avec les
autres durant leur évolution.
On dira que P1 et P2 sont concurrents si les exécutions
suivantes ne sont pas équivalentes : ( P1 II P2 ); ( P1 ; P2 );
(P2 ; P1) .
De plus ( P1 II P2 ) peut donner des résultats aléatoires si
certaines précautions ne sont pas prises. Les dangers d’une
telle exécution sont dus au fait que P1 et P2 utilisent des
ressources communes.
GÉNÉRALITÉS (PROCESSUS PARALLÈLES)
197. 197
Selon que les processus concurrents se connaissent
mutuellement ou pas, on distingue deux formes
d’interactions:
Compétition. Les processus ne se connaissent pas (i.e. ils
ignorent leur existence mutuelle) mais ils rentrent en
conflits pour l’utilisation des ressources
communes/partagées (e,g. fichier).
Pour résoudre les conflits entre les processus, on utilise des
règles d’utilisation de ressources. Ces règles visent à
sérialiser dans le temps les utilisations d’une ressource
donnée par les processus.
GÉNÉRALITÉS (PROCESSUS PARALLÈLES)
198. 198
Selon que les processus concurrents se connaissent
mutuellement ou pas, on distingue deux formes
d’interactions:
Coopération. Les processus se connaissent mutuellement
et échangent des informations (communiquent) pour traiter
un même problème. Ils peuvent aussi rentrer en
compétition pour des ressources partagées.
Un processus est dit coopératif s’il peut affecter les autres
processus en cours d’exécution dans le système ou être affecté
par eux.
GÉNÉRALITÉS (PROCESSUS PARALLÈLES)
199. 199
Résoudre une compétition consiste à définir les règles
d’accès simultanés aux ressources partagées considérées
comme objets de compétition et établir des mécanismes de
contrôle permettant d’imposer ces règles aux processus.
La synchronisation des processus permet de définir et de
réaliser ces mécanismes en assurant le respect des
contraintes liées à la progression des processus, c.-à.-d,
capables de faire attendre un processus qui tenterait des
actions ne respectant pas ces contraintes.
GÉNÉRALITÉS (RÔLE DE LA SYNCHRONISATION)
200. 200
La synchronisation des processus permet de définir et de
réaliser ces mécanismes en assurant le respect des
contraintes liées à la progression des processus, c.-à.-d,
capables de faire attendre un processus qui tenterait des
actions ne respectant pas ces contraintes.
La synchronisation se fait par les mécanismes suivants :
Exclusion Mutuelle (mutex)
Sémaphores
Régions Critiques
Moniteurs
GÉNÉRALITÉS (MÉCANISMES DE LA SYNCHRONISATION)
201. 201
Tout comme les processus, les threads POSIX
fonctionnent de manière asynchrone et peuvent donc
partager entre eux les variables globales et les
descripteurs de fichiers de processus. Une gestion de
l'accès concurrentiel doit donc être introduite.
La norme POSIX offre de nombreux mécanismes de
synchronisation:
Les verrous (ou mutex)
Les sémaphores.
Les moniteurs
GÉNÉRALITÉS (MÉCANISMES DE LA SYNCHRONISATION)
202. 202
Lorsque plusieurs processus s’exécutent sur un
ordinateur, monoprocesseur ou multiprocesseur, ils sont
amenés à partager des ressources communes soit
volontairement s’ils coopèrent pour traiter un même
problème, soit involontairement parce qu’ils sont obligés
de se partager les ressources de l’ordinateur.
Malheureusement, le partage des variables sans
précaution particulière peut conduire à des résultats
imprévisibles.
EXCLUSION MUTUELLE (POSITION DU PROBLÈME)
203. 203
Exemple du compte bancaire
Soient deux transactions (processus) P1 et P2 lancées en
parallèle de deux terminaux différents et pouvant consulter et
modifier simultanément un même compte CCP de valeur
initiale C0 centralisé dans un fichier commun F. P1 effectue un
dépôt (crédit) et P2 effectue un retrait (débit) .
EXCLUSION MUTUELLE (POSITION DU PROBLÈME)
Transaction 1 Transaction 2
Cpt est une variable locale.
A1 : Lecture du compte
Lire Cpt;
B1 : Modification du compte
Cpt = Cpt+SV ;
C1 : Réécriture du compte
Ecrire Cpt ;
Cpt est une variable locale.
A2 : Lecture du compte
Lire Cpt;
B2 : Modification du compte
Cpt = Cpt-SR ;
C2 : Réécrire du compte
Ecrire Cpt ;
204. 204
Exemple du compte bancaire
1er cas : Si l’exécution de P1 et P2 est purement séquentielle (
P1 ; P2 ou P2 ; P1) il n’y a aucun problème car il n’y a pas
d’accès simultané au même compte . Le résultat final du
compte est C0+SV-SR (résultat correct).
2ème cas : Si l’exécution de P1 et P2 est parallèle ( P1 II P2 ), il
y a un risque car il y a accès simultané au même compte.
EXCLUSION MUTUELLE (POSITION DU PROBLÈME)
205. 205
Exemple du compte bancaire
2ème cas : Si l’exécution de P1 et P2 est parallèle, il y a un
risque car il y a accès simultané au même compte. Exemple:
Normalement le résultat final correct devrait être C0+SV-SR :
l’exécution parallèle de P1 et P2 prise sans précautions entraine
une incohérence dans le résultat final.
EXCLUSION MUTUELLE (POSITION DU PROBLÈME)
Ordre d’exécution Processus 1 Processus 2
1 A1:Lire Cpt ;
2 A2: Lire Cpt ;
3 B1: Cpt = Cpt+SV
4 B2: Cpt = Cpt-SR
5 C1: Réécrire Cpt
6 C2: Réécrire Cpt
Valeur finale du Compte Cpt-SR
206. 206
Exemple du compte bancaire
2ème cas : Si l’exécution de P1 et P2 est parallèle, il y a un
risque car il y a accès simultané au même compte.
Pour éviter cette incohérence, il faut empêcher l’exécution
parallèle de P1 et P2. Les séquences de P1 et P2 doivent
être exécutées en Exclusion Mutuelle.
C’est le compte CCP commun (initialement égal à C0) qui
constitue la ressource critique, et les séquences de lecture,
modification et d’écriture du compte s’appellent sections
critiques de P1 et P2 respectivement.
EXCLUSION MUTUELLE (POSITION DU PROBLÈME)
207. 207
Une section critique (SC) est un ensemble d’instruction
d’un programme qui peuvent engendrer des résultats
imprévisibles lorsqu’elles sont exécutées simultanément
par des processus différents.
D’une manière générale, on peut dire qu’un ensemble
d’instructions peut constituer une SC s’il y a des
ressources partagées, mais l’inverse n’est pas vrai.
Pratiquement, les SC doivent être détectées par les
concepteurs de programmes
EXCLUSION MUTUELLE (SECTION CRITIQUE)
208. 208
EXCLUSION MUTUELLE (SECTION CRITIQUE)
P1 P2
A1
B1
C1
A2
B2
C2
Section Critique
Ressource commune
« compte bancaire »
Exemple du compte bancaire
209. 209
Pour éviter toute utilisation incorrecte d’une ressource
critique, les Sections Critiques (SC) qui la manipulent
dans les différents processus ne doivent jamais s’exécuter
simultanément.
Autrement dit, ces SC doivent s’exécuter en Exclusion
Mutuelle (EM ou mutex), c-à-d une SC ne peut être
entamée que si aucune autre SC du même ensemble n’est
en exécution.
EXCLUSION MUTUELLE (DÉFINITION)
210. 210
Le principe général d’une solution garantissant EM:
EXCLUSION MUTUELLE (PRINCIPE)
211. 211
Le principe général d’une solution garantissant l’EM:
Avant d’exécuter une SC, un processus doit s’assurer qu’aucun
autre processus n’est en train d’exécuter une SC du même
ensemble. Dans le cas contraire, il ne devra pas progresser tant
que l’autre processus n’aura pas terminé sa SC.
Avant d’entrer en SC, le processus doit exécuter un protocole
d’entrée. Le but de ce protocole est de vérifier justement si la SC
n’est occupée par aucun autre processus.
A la sortie de la SC, le processus doit exécuter un protocole de
sortie de la SC. Le but de ce protocole est d’avertir les autres
processus en attente que la SC est devenue libre.
EXCLUSION MUTUELLE (PRINCIPE)
212. 212
L’EM des processus dans leurs SC n’est garantie que si les
protocoles d’entrée et de sortie sont correctement utilisés.
En effet, en cas où ces protocoles sont mal construits, les
problèmes suivants peuvent se produire: :
L’interblocage qui caractérise une situation où les processus ne
peuvent plus progresser par manque de ressources. Chaque
processus détient des ressources dont l’autre a besoin.
La famine qui est une situation où certains processus n’accèdent
jamais à leurs sections critiques et sont ainsi mis en attente
indéfiniment alors que d’autre accèdent à leurs sections critiques
selon leurs besoins.
EXCLUSION MUTUELLE (PRINCIPE)
213. 213
Pour étudier et comparer les solutions au problème de
l’EM, on se donne un ensemble d’hypothèses de
travail (énoncées par DIJKSTRA) :
1) Les vitesses relatives des processus en compétition
sont quelconques et inconnues .
2) On suppose que tout processus qui entre en section
critique en sort au bout d’un temps fini.
3) L’ordre d’accès à la ressource critique est quelconque.
EXCLUSION MUTUELLE (HYPOTHÈSES)
214. 214
La solution au problème de l’EM doit avoir les propriétés
suivantes (propriétés de DIJKSTRA) :
a) A tout instant, un processus au plus peut se trouver
en section critique.
b) Si aucun processus n’est en SC et que plusieurs
processus sont en attente de la ressource critique,
alors l’un d’eux doit pouvoir y entrer au bout d’un
temps fini. La solution doit éviter qu’un blocage
mutuel des processus en attente de la ressource
critique dure indéfiniment alors que celle-ci est libre.
EXCLUSION MUTUELLE (PROPRIÉTÉS)
215. 215
La solution au problème de l’EM doit avoir les propriétés
suivantes (propriétés de DIJKSTRA) :
c) Si un processus est bloqué hors de sa SC, ce blocage
ne doit pas empêcher l’entrée d’un autre processus en
SC.
d) La solution doit être la même pour tous les
processus ; aucun processus ne doit jouer un rôle
privilégié.
EXCLUSION MUTUELLE (PROPRIÉTÉS)
216. 216
Contrôler la compétition entre processus, revient à
trouver une solution au problème de l’EM mutuelle.
Différentes approches existent
EXCLUSION MUTUELLE (RÉALISATION)
217. 217
EXCLUSION MUTUELLE (RÉALISATION)
Réalisation
de l’EM
Solutions
Matérielles
Masquage des Interruptions
Instructions Spéciales
Solutions
Logicielles
Attente Active
Algorithme de
Dekker
Algorithme de
boulanger
Attente Passive
Verrous
Sémaphores
Moniteurs
Quelque soit la solution, elle
doit garantir les 4 propriétés
énoncées par DIJKSTRA.
218. 218
Matériellement, une EM peut être réalisée en
1. Interdisant (masquant) les interruptions pendant qu’une
variable partagée est modifiée. De cette façon, on pourra être
sûr que la séquence courante d’instructions s’exécute en ordre
sans aucune réquisition.
2. Utilisant des instructions matérielles spéciales qui
permettent soit de tester et modifier le contenu d’un mot-
mémoire (Ex: instruction TAS), soit d’échanger le contenu de
deux mots (Ex: instruction SWAP) d’une manière atomique
(indivisible).
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
219. 219
1. Masquage des Interruptions: Il faut rendre les SC
indivisibles en inhibant, durant leur exécution, les
interruptions par masquage.
N’est accessible qu’aux programmeurs privilégies (super
utilisateurs) pour des raisons de fiabilité.
Fonctionnel que sur des machines monoprocesseurs.
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
Entrée en SC : Masquage des Interruptions;
Accès à la ressource : <SC>
Sortie de la SC : Démasquage des Interruptions;
220. 220
2. Instructions Spéciales: permettent de lire et de
modifier une ou plusieurs variables communes d’une
manière indivisible (instructions atomiques). Par
conséquent, si deux processus exécutent simultanément
ces instructions, l’un d’eux sera mis en attente.
Fonctionnelle sur des machines multiprocesseurs
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
221. 221
A. Instruction TAS (Test And Set) consiste à déclarer
une variable « verrou » donnant l’état de la ressource
critique (vrai ou 1 ressource occupée ; faux ou 0
ressource libre) et à garantir une EM au niveau machine
entre les processus désirant tester et modifier la variable
d’état « verrou ». Le code source de cette fonction peut
être assimilée comme suit:
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
int TAS(int* verrou)
{ int old;
old = *verrou;
*verrou = 1;
return old; }
222. 222
A. Instruction TAS (Test And Set): Soit verrou une
variable commune aux processus, concernée par la SC.
Elle doit être initialisée à faux (ressource libre).
une variable volatile est une variable sur laquelle aucune
optimisation de compilation n'est appliquée ainsi il n’y aura pas
de risque d’utiliser ses valeurs mises en cache, rendant ainsi le
code ci-dessus erronée.
Attente Active
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
Initialisation : volatile int verrou = 0;
Demande d’entrée en SC : while (TAS(&verrou));
Accès à la ressource : <SC>
Fin et Sortie de la SC : verrou = 0 ;
223. 223
B. Instruction SWAP permet d’échanger le contenu de
deux mots de manière atomique. Sa forme générale est
la suivante :
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
void SWAP (int* x, int* y)
{
int z;
z = *x;
*x= *y;
*y = z;
}
224. 224
B. Instruction SWAP: permet de réaliser EM en utilisant
deux variables:
«verrou » une variable commune aux processus concernée par la
SC. Elle doit être initialisée à faux.
«cle» une variable locale au processus, initialisée à vrai.
Attente Active
EXCLUSION MUTUELLE (SOLUTIONS MATÉRIELLES
Initialisation globale: volatile int verrou = 0;
Déclaration locale: int cle;
Demande d’entrée en SC : cle = 1;
do SWAP (&verrou, &cle); while (cle == 1) ;
Accès à la ressource : <SC>
Fin et Sortie de la SC : verrou = 0 ;