Académique Documents
Professionnel Documents
Culture Documents
Yann Morère
Septembre 2001
Table des matières
Introduction 1
i
2.8 Fonctionnement d’un système informatique . . . . . . . . . . . . . . . . . . . . . 17
2.9 Structure d’entrées/sorties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.9.1 Comment cela fonctionne . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.10 Structure de Stockage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.11 Protection du système informatique . . . . . . . . . . . . . . . . . . . . . . . . . 20
4 Les Processus 31
4.1 Concepts élémentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.1.1 Le processus et son espace adresse . . . . . . . . . . . . . . . . . . . . . . 31
4.1.2 Le kernel (noyau) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.1.3 Mode, espace et contexte . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.1.4 États d’un processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.1.5 Mécanismes de gestion de processus . . . . . . . . . . . . . . . . . . . . . 33
4.2 Ordonnancement (Scheduling) de processus . . . . . . . . . . . . . . . . . . . . . 35
4.2.1 Rôles des ordonnanceurs (répartiteurs, Schedulers) . . . . . . . . . . . . 35
4.2.2 Files d’ordonnancement . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.2.2.1 Traitements par lots (batch) . . . . . . . . . . . . . . . . . . . . 36
4.2.2.2 Multiprogrammation sans temps partagé . . . . . . . . . . . . . 36
4.2.2.3 Répartiteur pour le temps partagé . . . . . . . . . . . . . . . . 36
4.2.2.4 Temps partagé avec gestion de la mémoire virtuelle . . . . . . . 38
4.2.3 Algorithmes d’ordonnancement . . . . . . . . . . . . . . . . . . . . . . . 38
4.2.3.1 Premier Arrivé, Premier Servi ou PAPS . . . . . . . . . . . . . 38
4.2.3.2 Plus court d’abord . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.3.3 Priorité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.3.4 Le tourniquet (Round Robin) . . . . . . . . . . . . . . . . . . . 41
4.2.3.5 Ordonnancement à listes multiples . . . . . . . . . . . . . . . . 42
4.2.3.6 Ordonnancement temps réel . . . . . . . . . . . . . . . . . . . . 42
4.2.4 Évaluation des algorithmes d’ordonnancement . . . . . . . . . . . . . . . 42
4.2.4.1 Essais sur le système en fonctionnement réel . . . . . . . . . . . 42
4.2.4.2 Analyse déterministe . . . . . . . . . . . . . . . . . . . . . . . . 43
4.2.4.3 Modèles de files d’attente . . . . . . . . . . . . . . . . . . . . . 43
4.2.4.4 Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
ii
4.3 Création de processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.4 Exemple du système Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.4.1 Fonctionnement de fork() . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.4.2 La notion de ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.5 Synchronisation de processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.5.1 Conditions de course (race condition) . . . . . . . . . . . . . . . . . . . . 46
4.5.2 Exclusion mutuelle avec attente active (busy wait) . . . . . . . . . . . . . 46
4.5.2.1 Variable de blocage (lock variable) . . . . . . . . . . . . . . 46
4.5.2.2 Désactivation des interruptions . . . . . . . . . . . . . . . . . . 47
4.5.2.3 Solution matérielle : TSL (Test and Set Lock ) . . . . . . . . . . 47
4.5.2.4 Alternance stricte . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.5.3 Problèmes classiques de synchronisation de processus . . . . . . . . . . . 49
4.5.3.1 Le problème des producteurs et des consommateurs (le buffer
limité) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.5.3.2 Le problème des philosophes dineurs . . . . . . . . . . . . . . . 49
4.5.3.3 Le problème du barbier endormi (sleeping barber ) . . . . . . . . 50
4.5.4 Les Sémaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.5.4.1 Définition d’un sémaphore . . . . . . . . . . . . . . . . . . . . . 50
4.5.4.2 Exemple d’implantation de sémaphores . . . . . . . . . . . . . . 50
4.5.4.3 Une solution au problème des producteurs et consommateurs . 51
4.5.4.4 Une solution au problème des philosophes dineurs . . . . . . . . 52
4.5.4.5 Une solution au problème du barbier endormi . . . . . . . . . . 53
4.6 Processus poids-legers et threads . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.6.2 Notion de thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.6.3 Abstraction fondamentales . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.6.3.1 Le point de vue du kernel . . . . . . . . . . . . . . . . . . . . . 55
4.6.3.2 Thread du kernel . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.6.3.3 Processus poids-léger (lightweight process ou LWP) . . . . . . . 57
4.6.3.4 Threads au niveau de l’usager . . . . . . . . . . . . . . . . . . . 57
5 Gestion de la mémoire 61
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.2 Monoprogrammation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.2.2 La liaison entre noms et adresses (address binding) . . . . . . . . . . . . 61
5.2.3 Espace adresse logique et espace adresse physique . . . . . . . . . . . . . 62
5.3 Multiprogrammation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.3.1 Multiprogrammation et utilisation de l’UCT et de la mémoire . . . . . . 63
5.3.2 Multiprogrammation à partitions fixes . . . . . . . . . . . . . . . . . . . 63
5.3.3 Multiprogrammation à partitions variables . . . . . . . . . . . . . . . . . 64
5.3.4 Allocation d’un trou libre . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.3.5 Représentation de l’espace libre . . . . . . . . . . . . . . . . . . . . . . . 65
5.3.5.1 Bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.3.5.2 Liste chaı̂née . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.3.5.3 Listes de trous de taille spécifiques . . . . . . . . . . . . . . . . 66
5.3.6 Limitations de ces techniques . . . . . . . . . . . . . . . . . . . . . . . . 66
5.4 La mémoire virtuelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.4.1 Pallier le manque de mémoire . . . . . . . . . . . . . . . . . . . . . . . . 67
5.4.1.1 Structures de chevauchement (overlays) . . . . . . . . . . . . . 67
iii
5.4.1.2 Segmentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.4.1.3 Pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.4.2 Généralisation à plusieurs processus . . . . . . . . . . . . . . . . . . . . . 73
5.4.3 Le va-et-vient (swap inswap out) . . . . . . . . . . . . . . . . . . . . . . 73
5.4.4 La demande de page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5.4.5 Performance de la mémoire virtuelle . . . . . . . . . . . . . . . . . . . . 74
5.4.6 Caractéristiques principales dun algorithme de demande de page . . . . . 75
5.4.7 Algorithmes statiques de remplacement de pages . . . . . . . . . . . . . . 75
5.4.7.1 PAPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
5.4.7.2 Remplacement aléatoire . . . . . . . . . . . . . . . . . . . . . . 76
5.4.7.3 LRU (Least Recently Used) . . . . . . . . . . . . . . . . . . . . 76
5.4.7.4 LFU (Least Frequently Used) . . . . . . . . . . . . . . . . . . . 76
5.4.7.5 L’anomalie de Belady et lalgorithme de remplacement optimal 77
5.4.8 Une approximations de LRU : l’algorithme de la seconde chance . . . . . 78
5.4.8.1 L’algorithme de la seconde chance . . . . . . . . . . . . . . . . 79
6 Interblocage 81
6.1 Introduction : définition et caractérisation . . . . . . . . . . . . . . . . . . . . . 81
6.1.1 Définition de l’interblocage (deadlock) . . . . . . . . . . . . . . . . . . . 82
6.1.2 Caractérisation de l’interblocage . . . . . . . . . . . . . . . . . . . . . . 82
6.1.3 Graphe dallocation des ressources . . . . . . . . . . . . . . . . . . . . . 82
6.1.4 Remarques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.1.5 Comment traiter le problème de linterblocage ? . . . . . . . . . . . . . . 86
6.2 Vagabondage théorique sur linterblocage . . . . . . . . . . . . . . . . . . . . . . 87
6.2.1 Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.2.2 Bibliographie réduite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.2.3 Mécanisme de demande de ressource . . . . . . . . . . . . . . . . . . . . 88
6.2.4 Interblocage et cycles dattente . . . . . . . . . . . . . . . . . . . . . . . 88
6.2.5 Mauvaises nouvelles (1ère partie) : problèmes non décidables . . . . . . 89
6.2.5.1 Introduction plus formelle à la théorie de la calculabilité . . . . 90
6.2.6 Une version plus faible du problème de linterblocage . . . . . . . . . . . 92
6.2.7 Mauvaises nouvelles (2e partie) : problèmes NP-complets . . . . . . . . . 92
6.2.8 Que faire ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.2.9 Le modèle qui en résulte . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.2.10 Les matrices dallocation de ressources . . . . . . . . . . . . . . . . . . . 95
6.3 Solutions au problème de l’interblocage . . . . . . . . . . . . . . . . . . . . . . 96
6.3.1 Évitement de l’interblocage . . . . . . . . . . . . . . . . . . . . . . . . . 96
6.3.1.1 États sûrs, risqués (unsafe) et interblocage . . . . . . . . . . . 96
6.3.1.2 L’algorithme du banquier . . . . . . . . . . . . . . . . . . . . . 98
6.3.2 La prévention de l’interblocage . . . . . . . . . . . . . . . . . . . . . . . 98
6.3.2.1 Condition d’exclusion mutuelle . . . . . . . . . . . . . . . . . . 99
6.3.2.2 Condition d’attente circulaire . . . . . . . . . . . . . . . . . . . 99
6.3.2.3 Condition de non réquisition . . . . . . . . . . . . . . . . . . . 99
6.3.3 Détection et résolution de l’interblocage . . . . . . . . . . . . . . . . . . 99
6.3.3.1 Résolution de l’interblocage . . . . . . . . . . . . . . . . . . . . 100
6.3.3.2 Résoudre par rollback. . . . . . . . . . . . . . . . . . . . . . . 100
6.3.4 La stratégie de l’autruche (ne rien faire) . . . . . . . . . . . . . . . . . . 101
iv
Table des figures
v
4.18 Le problème des philosophes dineurs . . . . . . . . . . . . . . . . . . . . . . . . 49
4.19 Le modèle classique tâche = processus . . . . . . . . . . . . . . . . . . . . . . . 55
4.20 Nouveau modèle : un processus peut comprendre plusieurs chaı̂nes de contrôle,
ou threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.21 Une des chaı̂nes de contrôle (threads) d’un processus peut bloquer sans que cela
affecte les autres threads de ce processus . . . . . . . . . . . . . . . . . . . . . . 56
4.22 Les processus poids-léger (lightweight process) sont vus par le kernel et en parti-
culier par le répartiteur qui leur offre l’accès au(x) processeur(s) disponible(s) . . 58
4.23 Cas des threads implantés par des librairies comme C-threads ou pthreads : le
répartiteur ne voit que les processus . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.24 Structure complexe combinant les deux types de threads usager : processus poids
léger et threads non supportés par le kernel . . . . . . . . . . . . . . . . . . . . . 59
6.1 Interblocage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.2 Processus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
6.3 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.4 Ressources allouées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.5 Ressources demandées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.6 État dinterblocage après que P3 a demandé R B. . . . . . . . . . . . . . . . . . 84
6.7 État impossible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.8 Graphe d’allocation de ressources (une ressource de chaque type). . . . . . . . . 85
6.9 Graphe d’attente correspondant . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.10 Graphe d’allocation de ressources (plusieurs de chaque type). . . . . . . . . . . 86
6.11 Graphe d’attente correspondant (plusieurs de chaque type). . . . . . . . . . . . . 86
6.12 Un autre graphe dallocation de ressources . . . . . . . . . . . . . . . . . . . . . 88
6.13 Graphe dattente correspondant à létat représenté à la figure précédente . . . . . 89
6.14 Module de prédiction de chronologie des besoins en ressources. . . . . . . . . . . 90
6.15 On suppose que lon dispose dune chronologie des demandes de ressources . . . 92
6.16 Exemple de fonction dordre O(n) . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.17 Temps dexécution approximatif en fonction de la complexité algorithmique et
de la taille n de lentrée (tiré du livre de Garey & Johnson cité plus haut). On
suppose ici quune instruction élémentaire sexécute en 1 µs. . . . . . . . . . . . 93
vi
6.18 Effet de progrès technologiques sur la taille du plus grand problème traitable en
1 heure de calcul. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.19 Matrices dallocation de ressources : Requises = Max Détenues . . . . . . . . . . 95
6.20 Exemple de séquences dallocation/libération de deux ressources de type impri-
mante, I, et table traçante, T, par deux processus. Les instants tij correspondent
à des points dans le code des processus. . . . . . . . . . . . . . . . . . . . . . . 96
6.21 Séquencements possibles des allocations et libérations de ressources pour les deux
processsus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
vii
Liste des tableaux
ix
1 / 103
Introduction
Dans l’informatique d’aujourd’hui, les divisions bien distinctes entre la matériel informatique
(hardware) et les différentes formes de logiciel (software) : système d’exploitation (operating
system), langages de programmation et applications.
On peut par exemple installer différentes variantes d’UNIX (SunOs, Solaris, AIX, IRIX, Li-
nux, QNX, FreeBSD), sur des ordinateurs utilisant différentes générations de microprocesseurs
Digital Alpha, Sun Sparc, Intel x86, MIPS, Motorola 68K et PowerPc. De même des applica-
tions comme les traitements de textes, traitements d’images numériques, sont utilisables sur
différrentes plate-formes, Wintel, Macintosh ou Unix.
Ces divisions et distinctions actuelles ne se sont pas imposées d’emblée. Elles sont le résultat
(avec avantages et défauts) d’une longue évolution qui a plusieurs origines : mathématique,
philosophique, électronique, cybernétique, autimatique, économique et marketing.
3 / 103
Chapitre 1
Historique des Systèmes Informatiques
Le système d’exploitation peut alors être envisager comme un programme d’allocation de res-
sources. En effet le système informatique possède différentes ressources qui peuvent servir à
résoudre un problème : temps processeur, espace mémoire, espace de stockage des fichiers, pé-
riphériques d’entrée/sortie. Le SE est alors le gestionnaire de ces ressources, et les alloue aux
programmes et aux utilisateurs quand cela est nécessaire.
Bien sur il peut exister des requêtes imcompatibles au niveau des ressources, il faut alors
que le processeur choisisse la manière efficace est équitable pour les exploiter.
Afin de bien comprendre ce que font les systèmes d’exploitation, il est important de suivre
leur évolution durant les 30 dernières années.
Yann MORÈRE
1.3 La machine Analytique (1887) 5 / 103
¤ un organe de commande,
¤ un magasin (store) permettant de stocker les résultats des calculs intermédiaires,
¤ un moulin (mill) qui constituait l’unité arithmétique,
¤ et un mécanisme d’impression.
Il s’agit de la première machine de calcul programmable généraliste. Le même matériel pourra
être utilisé pour résoudre des problèmes différents. Il apparait alors la notion d’algorithme.
Au 19ème siècle, G. Boole et A. de Morgan, posent les fondations de la logique des mathé-
matiques modernes. Les notions de systèmes logiques, de calcul de propositions et de théorie de
la quantification sont développées par T. Skolem en 1919, S.C. Kleene 1936, W.V. Quine 1937,
K. Gödel 1930-1938.
La notion intuitive d’ensemble est formalisée par G. Cantor 1873 et A. Tarki 1923-1938 pour
éliminer de nombreux paradoxes.
En 1936, A. Turing présente un modèle formel d’une machine calculatoire. Ce modèle ma-
thématique détache complètement le processus de calcul des détails de l’implantation. Donc
pratiquement, tous les systèmes informatiques peuvent être modélisés comme une machine de
Turing.
Ces travaux permettent d’intégrer la notion de calculabilité : Existe-t-il un solution algo-
rithmique à un problème donné (même si on n’en a pas encore trouvé une).
Yann MORÈRE
1.3 La machine Analytique (1887) 7 / 103
PQ RSUT,VWX !#" $&%
')(*,+-/.-102*+3-4 +5
67 -*,+584 + 6#9 (*-/: ;<+
=> ? @BAC
DE >F E!GHIH @
CKJL)MNL<O G J,@ C E
$END
$LOAD
!#" $&%&
$FNT
$JOB
Yann MORÈRE
1.3 La machine Analytique (1887) 9 / 103
!#" $%&" ')(+*,"-$ ./(0%&"1 2#354)627398/:;&<
2?>@:A<B4C8/6 2>@:A<
= =
Lorsque plusieurs travaux sont sur un disque, il devient possible de faire de l’ordonnancement
(scheduling) de travaux. Le système d’exploitation maintient plusieurs travaux en mémoire à
la fois. Lorsque l’UC devient inactive, le SE commute sur un autre travail et l’exécute.
Les systèmes interactifs font leur apparition, l’utilisateur peut entrer directement des com-
mandes à l’ordinateur et obtenir les réponses (clavier, terminal à impression, terminal à écran
cathodique).
Dans ce cas l’utilisateur actif bloque la machine pour tous les autres. La solution est donc
la temps partagé, introduit par les systèmes MULTICS (MIT Bell Labset General Electric)
MULTiplexed Information and Computing Service et UNIX (K. Thompson, D. Ritchie, Bell
Labs).
Yann MORÈRE
11 / 103
Chapitre 2
Structure de systèmes informatiques
2.1 Introduction
Le but de cette partie est d’avoir une connaissance générale du fonctionnement de base
d’un système informatique. Ceci permettra ensuite de rentrer dans les arcannes du système
d’exploitation et d’en comprendre les différentes parties.
!"# !$%
'&(*)+$, ACB AEDGHJF IKH
LNM HJO+D P HQ HA!R
ATS*PUD!VHJA
de bus pour établir les connections entre les différents modules du système. Les caractéristiques
importantes du bus sont, sa largeur (en bits), la fréquence à laquelle il fonctionnne (en Mhz)
et le type de transfert autorisé. Il existe plusieurs standard, comme le bus ISA, PCI, EISA,
Microchannel...
permet de s’échanger des données. Patriquement tous les ordinateurs actuels ont cette archi-
tecture (Cf. figure 2.2). Les différences entre gros systèmes industriels et ordinateurs personnels
résident dans les performances des composants.
$%&'()*,+
- %& & .+ /
0 - (+//+ !
" ! #
13254
La mémoire est un organe passif qui répond à des à des ordres indiqués par les files de
contrôle du bus. En répons à un ordre d’écriture, elle range la valeur réprésentée par les fils
de données du bus dans un emplacement défini par les fils d’adresse du bus. En réponse à un
ordre de lecture, elle fournit sur les fils de données du bus la valeur mémorisée à l’emplacement
défini par les fils d’adresse. Le nombre de fils de données du bus définit les nombres de bits
des emplacements mémoire. C’est une caractéristique importante pour les performances de
l’ordinateur, puisqu’elle détermine le nombre de bits pouvant être lus ou écrits en mémoire par
une seul opération. Le nombre de fils d’adresse du bus définit la taille maximale de la mémoire
centrale. Le bus est géré par un contrôleur, parfois intégré au processeur, qui empêcheson
utilisation simultanée par plusieurs organes.
Yann MORÈRE
2.5 Les entrées/sorties 13 / 103
$%&'($)*+
&',.-+/0) =?>@ABDCFE@AGHIB"A@J3KL
%1 23*),&)"*+ LMAFNPOQ@J.KL
... ...
ou des opérations arithmétiques et logiques avec un ou deux opérandes. Pour ces dernières opé-
rations, un registre particulier, l’accumulateur, est souvent utilisé implicitement comme l’un des
opérandes et comme résultat. En général le déroulement de l’instruction entraı̂ne l’incrémenta-
tion du compteur ordinal et donc l’exécution de l’instruction qui suit. Notons que le transfert
d’une valeur dans le compteur ordinal entraı̂ne un branchement à l’adresse correspondant à
cette valeur. La tendance naturelle a été de contruire des processeurs avec un jeu d’instruction
de plus en plus large. On pensait que le programmeur utilisarait les instructions ainsi disponibles
pour améliorer l’efficacité de ses programmes. Ceci a conduit à l’architecture CISC (Complex
Instruction Set Computer ). Ce pendant on a constaté que les programmes contenaient toujours
les mêmes instructions, laissant une partie du jeu d’instruction très peu utilisé. Une nouvelles
famille de processeur a vu le jour avec une nouvelle architecture : l’architecture RISC (Reduced
Instruction Set Computer ), qui offre un jeu très réduit d’instructions simples mais très rapides.
Le principe elémentaire mis en œuvre pour l’échange de données entre deux constituants
physiques est donné en figure 2.4. En dehors des donnée proprement dites, deux liaisons sup-
plémentaires sont nécessaires pour permettre d’une part à l’émetteur de la donnée de signaler
la présence effective de cette donnée sur les fils correspondants, et d’autre part au récepteur de
signaler qu’il a lu la donnée.
Yann MORÈRE
2.6 Les interruptions 15 / 103
2o p)qmrLso2p
! t$u)vbwxEy4z){gz)|Xy "$#%'&)('('& *,+.-0/2143)526 728.99:);)<
}E~X4)'' 4}@.~ =2>@?'ACB.?'>ED4>GFH=I JLK)K)M,?N=>@O'P)K,DRQ0S)Q0B.>EO'P
i2j)kmlLni2j ^$_)`bacEd4e)fge)hXd
T,U.VXW4Y'Z.[@\,]Y
Fig. 2.5 – Mécanisme d’accès direct à la mémoire
Pendant toute la durée du transfert, le processeur est libre d’effectuer un traitement quel-
conque. La seule contrainte est une contrainte de ses propres accès mémoire pendant toute
cette même durée, car il doit parfois retarder certains de ses accès pour permettre au dispositif
d’accès direct à la mémoire d’effectuer les siens (d’ou le terme vol de cycle).
La limitation du débit inhérent au mécanismeest en général lié au débit potentiel de la
mémoire.
Dans le cas de périphériques rapides (autre qu’un clavier), si on utilise le système d’inter-
ruption simplement, l’UCT ne fait plus que gérer des interruptions, et n’a plus de ressources
pour les calculs. Le DMA permet de remédier à cela. Avec cet Accès Direct à la Mé-
moire, le contrôleur de périphérique transfert des blocs entiers de données, dans la mémoire
sans l’intervention de l’UCT.
On a alors une seul interruption par bloc à la place d’une interruption par octet.
peut signaler la fin d’une opération d’entrées/sorties précédemment demandées, ce qui permet
au système de reprendre l’exécution du programme interrompu.
Le mécanisme est obtenu en modifiant légèrement le fonctionnement du décodeur-séquenceurdu
processeur par l’introduction d’une troisième phase :
La prise en compte de l’interruption peut se faire de différentes manières. Puisqu’il s’agit d’in-
terrompre le déroulement normal des instructions, il suffit de modifier le compteur ordinal.
Mais comme l’on désire reprendre ultérieurement le programme interrompu, il faut aussi sau-
vegarder la valeur de ce compteur. En général, on utilise un PSW Program Status Word,
ou mot d’état du programme, qui contient en particulier, le compteur ordinal ainsi que certains
indicateurs sur l’état courant du processeur. La prise en compte de l’interruption consiste à ran-
ger en mémoire ce PSW dans un emplacement déterminé ou repéré par un registre particulier
comme le pointeur de pile et à charger à nouveau ce PSW.
Afin d’éviter de ranger inutilement en mémoire des registres, le processeur ne range que le
minimum lors de la prise en compte de l’interruption. Si l’on désire reprendre ultérieurement
le programme interrompu, les instructions qui constituent le traitement de l’interruption, sous-
programme d’interruption, doit ranger en mémoire le contenu de l’ensemble des registres du
processeur qui ne l’ont pas été lors de la prise en compte de l’interruption, pour permettre cette
reprise ultérieure. On nomme cela la sauvegarde du contexte. Lorsque le contexte est sauvegardé,
le sous-programme analyse la cause de l’interruption et effectue le traitement approprié. Il
peut ensuite restituer le contexte du programme interrompu. Il se termine par une instruction
spéciale qui demande au processeur de restituer le PSW du programme interrrompu, entraı̂nant
sa reprise effective. Il y a des difficultés si un nouvelle interruption arrive avant la fon du sous-
Yann MORÈRE
2.7 Notion d’appels système 17 / 103
[\^]_[!\`abc
MN!O#PRQSUTV!W#XRYZ
:;<=>;? @AB>
%&'()&* +,-) CED B<F =AG H
!#" $ .0/21!354 ) 1!376 '(,98 C AJILK< C A9H
Lorsque l’ordinateur est mis sous tension, un programme initial s’exécute (boot code, pro-
gramme d’amorçage). Son travail est d’initialiser tous les composants de l’ordinateur en partant
des registres de l’UCT jusqu’aux périphériques.
Ensuite il doit pouvoir charger le système d’exploitation et commencer à l’exécuter. Le SE
démarre alors le premier processus et attend un évènement. Le plus souvent il s’agit d’une
interruption matérielle ou logicielle. Le matériel interrompt l’UCT en lui envoyant un signal sur
le bus système. Dans le cas d’une interrruption logicielle il s’agit d’un appel système. L’UCT
arrête son travail actuel, et transfère l’éxécution à l’adresse de l’interruption. Là une routine
d’interruption s’exécute, et lorsqu’elle a terminé, l’UCT reprend son calcul.
Les interruptions sont très importantes, car c’est par elle que les programmes peuvent accé-
der au matériel. Ces interruptions sont en nombre fini, et il est possible d’accéder aux routines
d’interruption par l’intermédiaire d’une table stockée dans la mémoire basse. On parle alors de
vecteur d’interruptions. Ce tableau d’adresse est utilisé pour indexer un périphérique unique.
Mais pendant que nous exécutons notre routine d’interruption, il ne faut pas perdre le travail
que l’on était en train de faire. Donc le plus souvent l’adresse de l’instruction interrompue est
stockée dans la pile système (stack ).
Tout le système fonctionne comme cela. Dès que l’on veut atteindre un périphérique il faut
interrompre l’UCT.
Yann MORÈRE
2.10 Structure de Stockage 19 / 103
/1 0 / 12143516 /879 1:<;1 6 9 =>/ 79 1
!#"%$
&')(+* ,(.-
Il est alors possible de montrer une hiérarchie de stockage en partant des mémoires les plus
proche du processeur et donc du plus rapide, aux plus éloignées et plus lentes.
IJK L+MN?OPQHJL+MRN
SUTV7WX0Y[ZATC\V^`]X _Hab+cXY
Il est important de remarquer la très grande différence de vitesse de traitement entre les
mémoires volatiles et les disques. Donc afin de ne pas trop pénaliser la vitesse globale du système
et de pallier cette différence, les mémoires cache ont été ajoutées.
Elle sont chargées de stocker les données qui sont utilisées très souvent, afin que le système
n’aie pas à les recharger à partir d’un périphérique lent. Il est à noter que ce stockage n’est que
temporaire.
Mais ces mémoires rapides sont d’une taille limitée, donc la gestion du cache est très im-
portante. En effet un cache bien dimmensionné couplé à un programme de gestion astucieux,
peux éviter de nombreux accès à un périphérique lent comme les disques.
Yann MORÈRE
21 / 103
Chapitre 3
Structures des systèmes d’exploitation
3.1 Introduction
Il s’agit d’une partie très importante de tout système informatique.
Un système d’exploitation (SE ou OS) est un programme qui permet de faire la liaison entre
l’utilisateur et le matériel de l’ordinateur. Sans celui-ci les applications telles que les SGBD, les
outils PAO, les traitements de texte ne pourraient pas fonctionner. De plus, il doit permettre
à l’utilisateur d’exécuter ses programmes de manière pratique et efficace (avec par exemple les
API (de programmation) Application Program Interface et la gestion simultanée de plusieurs
programmes).
Ce système doit assurer le fonctionnement correct du système informatique. Il fournit aussi
certains services aux progammes et aux utilisateurs (faciliter la programmation par exemple).
Ils sont souvent différents d’un système à l’autre, mais on retrouve des services communs.
Le système d’exploitation peut aussi être vu comme un programme de contrôle qui vérifie
l’exécution des programmes utilisateurs afin d’éviter les erreurs et les mauvaises utilisations.
Pour cela il s’occupe principalement du contrôle des périphériques.
Une définition plus commune consiste à expliquer que le SE est le seul programme tournant
à tout moment dans l’ordinateur (on parle aussi de noyau ou kernel ).
Pour l’utilisateur final, le but principal est la commodité du système d’exploitation. L’ex-
ploitation efficace des ressources est alors un problème secondaire. Mais dans le cadre d’un
système partagé multi-utilisateurs, cet objectif est des plus important car ces systèmes coûtent
très cher et il est important de les rendre les plus efficaces possible.
Ces deux objectifs, commodité et efficacité, sont souvent contradictoires. Mais par le passé
la notion d’efficacité était la plus importante. c’est pour cela que la plupart des théories se
concentrent sur l’utilisation optimale des ressources du système.
! " #
$$%'& (*))+', -/.103254768.94;:03<=<=>@?BA'0C:1?@D5E=.
RT S RVU5W@X T
' ( ) * + , -
" ! # $ % &
Yann MORÈRE
3.3 Composants et fonctions 23 / 103
précédemment.
Yann MORÈRE
3.4 Structure d’un système d’exploitation 25 / 103
Couche 0 : matériel
couches qui vont composer le système de manière adéquate. Une soigneuse planification est
nécessaire. De plus ces implémentations sont souvent moins performantes que d’autres types de
structures. En effet par exemple pour faire un appel E/S (accès au matériel) il est nécessaire
de faire appel à toutes les couches. Chaque couche ajoute une surchage à l’appel initial.
Les systèmes actuels se portent donc sur une structure avec moins de couches et plus de
modularité (par exemple OS2).
Yann MORÈRE
3.4 Structure d’un système d’exploitation 27 / 103
DFEHG
IKJML NOPJ
'),
W3X5Y T3U5V
Z\[ ] ^_`
a bc [ d` c+e l mf\n g h ijkn+p w xq\y r s tuvy+{ |\ } ~ +
g ok r zv }
aura un faible nombre de fonctions élémentaires, mais on augmente du même coup le nombre
d’appels de fonctions pour toutes opérations que doit effectuer le kernel.
On oppose alors souvent les kernels dit monolithiques qui continuent à être indépendant
du matériel, mais ils sont de taille plus importante, aux microkernels qui n’offrent plus que
4 services minimaux :
¤ un mécanisme de communication interprocessus,
¤ un système de gestion mémoire,
¤ un niveau minimal de gestion de processus,
¤ un système de gestion des E/S de bas niveau.
Contrairement à un kernel monolithique, un microkernel n’est plus un système d’exploitation,
mais une base sur laquelle on peut construire un système d’exploitation.
Dans la famille des kernels monolithiques on retrouve la fameux kernel Linux, les WinNT
etc... de l’autre coté, on retrouve les implantations Mac OS, basée sur un microkernel Mach, ou
encore Solaris, la variante Unix de Sun. On peut noter aussi le développement de GNU Hurd,
un micronoyau, basé lui aussi sur Mach.
On peut alors lister les principaux avantages des deux architectures :
¤ Microkernel : portabilité, maintenance facile,
¤ Kernel monolithique : performance.
3.5.2 Le Mac OS
Il a été introduit en 1984. Ses principales caractéristiques sont les suivantes :
¤ Ce fût le premier ordinateur personnel grand public avec une interface graphique (exclu-
sivement).
¤ Contrairement à Windows, ou à X-Windows, l’environnement graphique n’est pas un
shell du Mac OS, mais fait partie intégrante du SE.
¤ Il s’agit d’un système mono-utilisateur.
¤ Son fonctionnement est multi-tâches coopératifs.
Yann MORÈRE
3.5 Exemple de systèmes d’exploitation 29 / 103
Ä Å Æ'Ç.ÈÉ Ê%Ë3ÇZÌIÍ'Ê%Î+Ç.È
Ï Ð Ñ'Ò.ÓÔ Õ%Ö3ÒZ×1Ø ÙÓ'Õ+Ø Ó Ø Ò
Ú ÛÜÝ.Þ'ß à+á3ÝUâÝ<ã
àääÝ<å ãÀãæãÜ.Ý.ç èÝ<ã !#"%$ $'&)+( *, -.) /1032 &54%6798, : ; -<)+/0 2 &)%-4= éëêìíUîIï'ð%ñ+í.ò
>?@AB?A?CED#FBGHIBAH
J5KL5MNPOQRJTSRLUNWVL1XRYZNW[V#\]L^N`_TJ5V1a#b5c%def f f
g#hi+jlk mnlPoZp qsrutUvw#x jyTj xw#z|{W}W~+ óëôõöZ÷ øùú.ö.û üö
+< +^'3<'.+<' +U Z. +<. Z^' ..#+<'% ýö.þÿö
T1¡ ¢T£¥¤ ¦#§¨©ªU§¨ «<¬
^®#¯°±³ ² ±´ µ ¶ ³ °·µ ¸¹ º ³ ¸.°» ³ ¶'±¥µ ¼½º¾R°¿À³ ² ¶'µ ¿Á¶'µ ¹+º ³ ¸.° ³ »'Â+à à Ã
¤ Il ne possède pas de vraie structure de niveaux. Il n’a pas non plus de kernel, le système
est composé d’un ensemble de managers :
. Event Manager, Manu Manager, Window Manager, Dialog Manager, Control Manager,
Help Manager, ....
. Ressource Manager, Component Manager...
. File Manager, Memory Manager...
. Image Compression Manager.
Contrairement à Unix, les processus Mac OS sont toujours liés à une application. Une appli-
cation est en avant-plan (foreground), et toutes les autres en arrière-plan (background). La
gestion des processus est basée sur la notion d’évènement.
Dans le Mac OS, il existe trois types d’évènements :
¤ événements de bas niveau (internes à une application) : activation ou remise à jour d’une
fenêtre suite à une pression ou un déplacement de la souris, l’insertion d’une disquette...
¤ événements du système d’exploitation, relatifs au changement d’application en avant-
plan.
¤ événements de haut niveau, relatifs aux communications entre applications.
Chapitre 4
Les Processus
Chaque processus possède deux objets spécifiques particulièrement importants qui sont gérés
par le kernel :
¤ l’espace usager (user area ou u area) : qui contient des informations sur le processus qui
sont utiles au kernel (liste de fichiers ouverts, valeurs des registres lorsque le processus
est interrompu). L’espace usager n’est pas accessible (en écriture) au processus, même si
il est parfois implanté dans son espace d’adresse.
¤ la pile du kernel (kernel stack ) : dans le cas d’un kernel réentrant comme celui d’Unix (c-
à-d autorisant plusieurs processus à être engagés concurrement dans des appels système),
il faut maintenir pour chaque processus la liste des séquences d’appels de fonctions.
Contexte processus et contexte système (process context et system context)
Le kernel peut opérer en contexte processus, c’est à dire pour le compte d’un processus
(en exécutant un appel système ou en traitant une exception). Il peut aussi opérer en
contexte système pour gérer les interruptions en provenance des périphériques.
Yann MORÈRE
4.1 Concepts élémentaires 33 / 103
&(' ) *,+.-/10*"2 N >@HP?BODADODCFQ R ED>JHJG SHJR IK?PCMTVL U cJdedef@g h"h iBh jMfMk lf
fMmDnMfMdej o pKqDh 3(4 5 6,78:9;"6"< =%6
W X YZP[@WYV\ ]B[@W X X@^PXXMWJ^P_ W ` W aVb r s t uPv@rtVwMxBvMr s sJyJsFr@z s {Ds@zPr | }~r
P@" DMK " PJ V
eP$JD ¡P¢ £ D¥ ¤ B @ eD PD
JP @D: B MM
Un processus est une entité active (dynamique), dont on peut étudier l’état au cours du
temps.
Un processus peut être dans 5 états différents (Cf. figure 4.2) :
¤ nouveau, le processus est en cours de création,
¤ prêt, le processus attend d’être affecté à un processeur,
¤ élu, les instructions sont en cours d’exécution,
¤ en attente (bloqué), le processus attend qu’un événement se produise (comme l’achève-
ment d’une entrée/sortie ou la réception d’un signal),
¤ fini, le processus a fini l’exécution.
"#"! $%#'&)( #+*-,/. 01 +2" 1 03
Æ Ç+È8É:Ê Æ Ë
Ì Í+ÎUÐ Ï ÊDÑÒ Ð ÇÈ8Ê Ê Ð Ç Ê ÐÓ ç:æ è ésê çUë çUæ ì:é í çî
"8 :8=>8 A C=D :H:
¸ ¹+º8»:¼ ¸ ½
8= R U +X=/u>+¡R¢)£_¤_ ¾ ¿+ÀUÂÁ ¼DÃÄ Â ¹º8¼ ¼  ¹ ¼ ÂÅ
Yann MORÈRE
4.2 Ordonnancement (Scheduling ) de processus 35 / 103
etc. etc.
Sur la plupart des systèmes modernes, le rôle du répartiteur de haut niveau se résume surtout
à accepter ou refuser une demande de chargement de processus en mémoire (espace mémoire
occupé, quota de processus atteint, charge courante du système est trop importante).
Dans un environnement à temps partagé et à mémoire virtuelle ; deux répartiteurs doivent
cohabiter : le répartiteur de bas niveau qui gère le temps partagé et un répartiteur de haut
niveau qui gère les transferts entre disque et mémoire (swap in et swap out).
Yann MORÈRE
4.2 Ordonnancement (Scheduling ) de processus 37 / 103
unvxw
ynzx{
|n}x~
x'y zR{|x'y&x } y6~Cy | ! "#"$%"#&' '6 $6#
( !*)+%, -*!. NPORQ
/1023'4 )#)$.') 0265 "$)7
m npo*qKr stn*uvs w
qArstvuPwyx
<2=?>A@CBDEF=AGHD2I
Yann MORÈRE
4.2 Ordonnancement (Scheduling ) de processus 39 / 103
à maximiser
taux d’utilisation de l’UCT (en %tage de temps
écoulé)
à maximiser
débit (throughput) : le nombre total de processus traités
par unité de temps
à maximiser
prédictabilité : une tâche donnée devrait toujours avoir
les mêmes temps de réponse et de virement
à maximiser
justice : en particulier aucun processus ne devrait souf-
frir de famine (starvation)
à minimiser
temps de virement (turnaround time) : temps écoulé
entre la soumission et la fin de l’exécution
à minimiser
temps d’attente (passé dans la file de bas niveau)
à minimiser
temps de réponse (pour un processus interactif, avant
la première sortie vers l’usager)
>@?BA
$%&'( ) &
*+ %,( - -.
& -
!#" /10 23 617 :; 415 <= 819
b@cBd
efghi jlki j g
CED FG HJIKL \1] ^_ `a
M LNOFK M L MQP RTS U V1W XY Z1[
sts
m1n o p qQr o u vxwTy
@B
En supposant que A arrive en premier suivi de B, une unité de temps plus tard, puis C une
unité de temps encore après. Comment les 3 processus vont-ils utiliser l’UCT dans les 30 unités
à venir ?
! " #$%
& ')*,( +
τn+1 = α · tn + (1 − α) · τn
où tn est le temps de service du dernier passage par l’UCT, τn est la prédiction qui avait
été faite avant ce passage, et τn+1 est la prédiction (corrigée) qui est faite pour la durée
de la prochaine giclée d’UCT du processus. Le paramètre α indique le poids que l’on veut
donner à l’historique.
4.2.3.3 Priorité
Il s’agit d’une forme générale du SJF, mais le critère de choix n’est plus simplement le temps.
On associe à chaque processus une priorité, et l’UCT est allouée au processus de plus haute
priorité. De même que pour le FJS, les processus de même priorité sont arbitrés par PAPS. Ce
type d’ordonnancement peut être fait avec ou sans réquisition.
Un des problèmes majeures de ce type de répartiteur est le blocage indéfini ou famine. En
effet, il peut laisser des processus de basses priorités attendre indéfiniment l’UCT. La solution à
ce type de problème est le vieillissement automatiques des processus. Cette technique consiste
à augmenter graduellement la priorité des processus attendant dans le système.
Yann MORÈRE
4.2 Ordonnancement (Scheduling ) de processus 41 / 103
C’est un algorithme d’ordonnancement avec réquisition spécialement conçu pour les systèmes
à temps partagé.
Le tourniquet ajoute juste à l’algorithme de PAPS un quantum de temps limitant la durée
des giclées de l’UCT. Avec ce type d’algorithme, un processus peut perdre le contrôle de l’UCT
de deux manières :
2. par réquisition :
& ')*,( +
35476
8 9 :<;=>?9::@:<A9?9B B9DC8 9
E 9D;>@= => E B9F B =9G?BIH JLK9 :NM@98 >=I:M#@9 $&% *,+ /,0 '&() 12 -.
8 G!C8 9A9 E H J9 G @&OD:P9 = G!JH A9
<¡¢£¤¥<¦¤§ §D¨
© D ¡£¥¢ ¢£ © §ª § ¢«¤§I¬ L® N¯¥ £¢I¯#¥ [&\\ WX & & & &
«t¨ ¦ © ¬ « ¥±°§²t¢ £ © §N¬ ¦
Yann MORÈRE
4.3 Création de processus 43 / 103
4.2.4.4 Simulation
À partir des modèles probabilistes déterminés précédement.
Exemple d’évaluation : temps d’attente moyen (TAM)
La file d’attente des processus prêts contient quatre processus, A, B, C et D (arrivés dans
cette ordre), dont les temps d’exécution respectifs sont 16, 2, 8 et 12 unités de temps.
Quel est le TAM pour PAPS ? Pour SJF ?
Cas de PAPS : T AM = [0 + 16 + (16 + 2) + (16 + 2 + 8)]/4 = 15.
temps d’attente moyen sur une longue période de temps, en utilisant les temps d’attente
des processus tout au long de leur durée de vie.
C’est à dire, définir d’une part le programme (ou suite d’instructions) décrivant l’activité du
processus, ainsi que l’état initial de ces données, de ses variables et des registres du processeur.
La plupart des sytèmes permettent cette création dynamique des processus. De plus la rela-
tion entre le processus créateur et le processus créé est importante, ce qui conduit à structurer
l’ensemble des processus sous la forme d’un arbre et à maintenir cette structure.
Lors de la création de processus, le processus créé est relié automatiquement comme fils du
processus créateur (père).
Lors de la fin d’exécution normale d’un processus P , deux solutions sont possibles :
¤ le destruction de P n’est effective que lorque tous ses fils sont eux-mêmes achevés. Ceci
est nécessaire lorsque le contexte initial du fils est inclus dans celui du père P . En effet
la destruction de celui-ci entrainerai la perte d’une partie du contexte du fils et donc un
déroulement anormal s’il pouvait survivre à son père.
¤ la destruction de P entraı̂ne le rattachement de ses fils à l’un de ses ancêtres. Cependant
comme l’ascendance du processus P n’a pas connaissance des actions de ce dernier, on
rattache les fils au processus qui a initialisé le travail (login), soit à la racine qui est un
processus standard et éternel.
Sous Unix la fonction de création de processus est la fonction fork(). fork() duplique
l’espace d’adresse du processus original (code, variables, contenu des registres).
Yann MORÈRE
4.4 Exemple du système Unix 45 / 103
Il est important de comprendre que les zones de données, de variables sont identiques à la
création du nouveau processus. Par contre par la suite les deux processus sont complètement
indépendants et n’ont pas de données communes.
Si le processus père se termine avant le processus fils, le fils est rattaché au processus racine de
manière à conserver la structure d’arbre. Le processus père peut aussi attendre la terminaison
de l’un de ses fils par la fonction id_fils = wait(&status). Cette fonction retourne dans
id_fils, le numéro d’un processus fils qui s’est terminé, et la variable status contient un code
indiquant la manière dont le processus s’est terminé. Si aucun fils ne s’est terminé et qu’il y en
a encore d’actifs, le processus père est mis en attente d’une terminaison de l’un de ses fils.
Par ailleurs le système Unix fourni une fonction exec qui permet à un processus de changer
de programme en cours d’exécution. Elle remplace les anciennes données par celle du nouveau
programme.
Yann MORÈRE
4.5 Synchronisation de processus 47 / 103
! " # %$& %! ')(! *+ + , " #-!
./01 2,3 452 06 6 7 8:9;=< 1 7 4?>5;-@ 2 ;8BA0C2 08:91D0E93 6 FHG
IJK LM-K LN-OQP R N?L STU+VW X R NQY ZR [?LY Y LC\+] \HX W,TW T
X N5W LK K R ^:MVL%_&X Y\ UU+`OLZY \%K L+P P R VK ULCM-\HK W \Ha)TL
bcedfQg:hjikh,f:lnmehpo,q%f%l&h&rQl&h
Tab. 4.3 – Exemple où la variable verrou ne protège pas l’accès à la ressource partagée
Sur cette exemple, on remarque que ce problème pourrait être éviter si la commande qui permet
de tester la ressource et de la réserver se faisait en une seul fois. Il s’agit de la notion de
commande atomique.
¤ de plus un processus qui a une très longue section non critique peut en bloquer un autre
qui attend que sont tour vienne. En effet l’algorithme requiert une alternance stricte de
processus dans l’exécution de leurs sections critiques. Par exemple si le processus P1 est
prêt à entrer dans sa section critique après une première exécution de son programme
(le tour est donc au processus P0 ), donc a_qui_le_tour vaut 0, et ce dernier n’a
pas encore fini sa section non critique, il bloque donc le processus P0 en section non
critique.
Problème généraux avec l’alternance stricte
¤ L’attente active gaspille du temps UCT. Il faut réactiver régulièrement tous les pro-
cessus qui veulent entrer dans leur section critique afin qu’ils puissent vérifier si leur
tour est enfin arrivé.
¤ En règle générale, l’alternance stricte ne peut pas garantir qu’un processus n’attende
indéfiniment, ou qu’un processus bloque d’autres processus en dehors de sa section
critique.
Exemple : inversion de priorités
Soit deux processus, H (haute priorité) et B (basse priorité). La règle à suivre est la
suivante : si H est prêt, alors il doit être activé (élu). Il faut donc trouver une solution
!"$# "$#%'&("$ )!"
* %!,+- . /0!#%!1) !324 .5"2'/ 4 * %!
E
I$J K4L FG H
qui combine la notion de commande atomique (commande très courte qui ne peut pas
être interrompue) avec un mécanisme de blocage/réactivation qui ne gaspille pas l’UCT
comme le fait l’attente active.
Yann MORÈRE
4.5 Synchronisation de processus 49 / 103
Le problème est de synchroniser les actions des philosophes de manière à ce qu’ils parviennent
à manger et à penser.
Yann MORÈRE
4.5 Synchronisation de processus 51 / 103
consommer_item(&item) ;
}
}
Yann MORÈRE
4.5 Synchronisation de processus 53 / 103
etat[i]=pense ;
test(GAUCHE) ; //si les phil. gauche attendait sa f.d. on le re-
veille
test(DROITE) ; //si les phil. droit attendait sa f.g. on le re-
veille
up(&mutex) ;
}
}
void test(int i) //on verifie que les 2 fourchettes sont libres
{
if (etat[i] == faim && etat[GAUCHE] != mange && etat[DROITE] != mange)
{
etat[i]=mange ;
up(s+i) ; //permet de reveiller le voisin
}
}
#define CHAIRS 5
semaphore customers = 0 ;
semaphore barbers=0 ;
semaphore mutex=1 ;
int waiting=0 ;
void barber(void)
{
while (TRUE)
{
DOWN(customers) ; /*go to sleep if no customers*/
DOWN(mutex) ;
waiting=waiting-1 ;
UP(barbers) ;
UP(mutex) ;
cut_hair() ;
}
}
void customer(void)
{
DOWN(mutex) ;
if (waiting lessthan CHAIRS)
{
waiting=waiting+1 ;
UP(customers) ;
UP(mutex) ;
DOWN(barbers) ;
get_haircut() ;
}
else
{
UP(mutex) ;
}
}
Même en utilisant des sémaphores, il est possible que se posent d’autres problèmes de synchro-
nisation :
¤ difficulté de programmation,
¤ interblocage
Yann MORÈRE
4.6 Processus poids-legers et threads 55 / 103
!#"
¤ chaque processus ayant toujours son espace d’adresse propre, on multiplie le nombre
d’espaces d’adresse à charger en mémoire. En particulier, si l’application fait appel à
plusieurs instances d’un même processus, on retrouvera plusieurs copies quasi-identiques
du même espace d’adresse (le code en particulier) en mémoire.
¤ l’exécution de l’application impose la résolution d’un complexe problème de communica-
tion entre processus.
L’idée est de conserver la notion de plusieurs chaı̂nes d’exécution à l’intérieur d’une même
application, tout en limitant les problèmes de communications.
!"$#%'&
Fig. 4.20 – Nouveau modèle : un processus peut comprendre plusieurs chaı̂nes de contrôle, ou
threads
#$%
&'(
,.-0/ 13245., )*+
Fig. 4.21 – Une des chaı̂nes de contrôle (threads) d’un processus peut bloquer sans que cela
affecte les autres threads de ce processus
Yann MORÈRE
4.6 Processus poids-legers et threads 57 / 103
* +-,./&021131
4 5-678&92::;:
< (7 = >:@?@A BCD926FEG5H5HIKJ
L MONP&QR(SUTWVYXZQP[\Q]
^-_`aDbcFaDdec__c
Fig. 4.22 – Les processus poids-léger (lightweight process) sont vus par le kernel et en particulier
par le répartiteur qui leur offre l’accès au(x) processeur(s) disponible(s)
Thread usager 52 66
L’inconvénient majeur de ce type de thread est qu’ils ne permettent pas de tirer parti des
architectures multi-processeurs : quel que soit le nombre d’UCT, au plus un thread de chaque
processus peut être élu à un instant donné. Si on utilise ensemble les deux types de threads
usager (supportés par le kernel ou pas), on obtient des structures de threads plus sophistiquées.
Yann MORÈRE
4.6 Processus poids-legers et threads 59 / 103
H I J L M O P Q
G !#"%$&')(#*+
K N
,-./1023/1452--2
Fig. 4.23 – Cas des threads implantés par des librairies comme C-threads ou pthreads : le
répartiteur ne voit que les processus
U V W X Y Z [ \
! "#$&%'(()+*
T ,.-/0124356879:
_ ` ^ ]
;<=>$?@&>$AB@<<@
Fig. 4.24 – Structure complexe combinant les deux types de threads usager : processus poids
léger et threads non supportés par le kernel
Chapitre 5
Gestion de la mémoire
5.1 Introduction
Il existe dans un système informatique plusieurs supports de conservation de l’information.
Ces supports ou types de mémoire sont organisés selon une hiérarchie en couche comme on l’a
vu dans le chapitre 2. Au sommet se trouve les registres (petite capacité, grande vitesse, coût
elevé). En bas de la pyramide on retrouve les supports magnétiques et optiques de mémoire
secondaire (grande capacité, faible coût, lents).
Afin d’obtenir une bonne performance du système informatique, il est important de tirer le
meilleur parti des types de mémoires les plus rapides pour pallier les limitations des plus lents
et à l’inverse d’exploiter au maximum les types de mémoire les plus abondants pour simuler les
types plus rapides disponibles en quantités limitées.
Nous nous concentrerons sur deux points :
¤ l’utilisation de la mémoire secondaire pour émuler la mémoire réelle, que l’on appelle
aussi les techniques de mémoire virtuelle,
¤ l’utilisation de la mémoire principale (RAM) pour tirer une meilleure performance des
systèmes d’entrées/sorties appellée aussi technique de cache disque.
5.2 Monoprogrammation
5.2.1 Introduction
Nous nous interesserons dans un premier temps au cas d’un seul processus chargé en mé-
moire. La plupart des concepts que nous allons voir s’appliquent au cas de la multi-programmation.
678848:99 ;
<=>?@ A Y Z&[&\ ]^_M`"^
BC A "D E$F&GH(> I*>H&GJ acbed Z a$f$bd Z&g4h$^_
AJ-KMLON ^i-jMkOl
mnopnq r r s
PQRSQT U U V tuq psn
WXT SVQ
vwxyz{ |
"!$#&%'( )*'&%+ }~ | "$&(y *y&
+-,/.10 23"2242 |-/1
55
!"# $#% &'(#)$ %+* %
$#% ,-/.102)'-3
?@ A B C C B
NO P D GE F C HIJKB
4 576/598;:=< >
L ML
QR ST TVUWXQ RSYQU ZU\[GQ^] `U _ba U R R U c Rd];a S] R U e e SfU
Yann MORÈRE
5.3 Multiprogrammation 63 / 103
5.3 Multiprogrammation
5.3.1 Multiprogrammation et utilisation de l’UCT et de la mémoire
Un des objectifs de la multiprogrammation est une meilleure utilisation de l’UCT. Si l’on
considère le modèle simpliste d’un système sur lequel n processus s’exécutent en concurrence, n
est alors appelé le degrés de multiprogrammation du système. Si l’on suppose que les n processus
passe tous une fraction p de leur temps à affectuer des E/S, on voit que le taux d’utilisation de
l’UCT est :
T UU CT = 1 − pn .
90
80
70
Taux d’utilisation de l’UCT
60
50
40
30
20
10 20% E/S
50% E/S
80% E/S
0
0 1 2 3 4 5 6 7 8 9 10
Degrés de multiprogrammation
Fig. 5.3 – Taux d’utilisation de l’UCT pour divers taux d’E/S et nombre de processus
LCMNCNCO CCC
#$ % & ' & ' ( )+* hi j k l k l m n+o
HIJCJCK CC
EFCFCFCG CCC
=> ? @
Fig. 5.4 – Deux types de répartiteurs de haut niveau : répartiteurs à files multiples (une par
partition) et répartiteur à file unique
"! #$&% '(*) +-,/. 0-132 45&6 78 9 : ;/<
Fig. 5.5 – Occupation de la mémoire pour la séquence d’exécution des processus donnée dans
le cas d’une gestion de la mémoire à partitions variables
Yann MORÈRE
5.3 Multiprogrammation 65 / 103
Observations
1. L’utilisation de partitions variables ne résoud pas le problème de la fragmentation externe :
si le processus F se présente avant que E ne se termine, il devra attendre faute de trou
mémoire assez grand.
2. Afin d’éviter un fragmentation externe trop importante, on peut avoir à ré-introduire le
problème de la fragmentation interne : par exemple lors du passage de (f) en (g), plutôt
que de laisser un trou de très petite taille entre C et D, on peut préférer donner tout
l’espace libre à D.
Solutions pour 1 et 2
¤ Lorsque le niveau de fragmentation externe de la mémoire devient trop important, ou
lorsqu’une demande d’allocation de mémoire ne peut être satisfaite, on effectue une com-
paction de la mémoire, de manière à regrouper les trous isolés en trous plus importants :
. un trou à une extrémité de la mémoire usager,
. un trou au centre de la mémoire usager,
. un trou juste assez grand pour la demande reçue.
¤ Le SE peut aussi effectuer une opération de ramasse-miettes (garbage collection) à
chaque fois que de la mémoire est libérée dans le monceau (heap).
1. Le premier trou disponible (First Fit). On effectue une recherche parmi les trous
disponibles. Le premier trou de taille suffisante qui est rencontré est choisi. Cette
technique est la plus rapide.
2. Le plus petit trou disponible (Best Fit). Le plus petit trou de taille suffisante est
sélectionné. Il faut donc tester tous les trous disponibles avant d’en choisir un.
3. Le plus grand trou disponible (Worst Fit). Sauf s’il existe un trou ayant exactement
layant exactement la taille la taille requise (auquel cas on le selectionne), le plus grand
trou disponible est sélectionné. La raison est la suivante : on veut que le trou restant, un
fois que l’espace demandé a été alloué, soit le plus grand possible.
Quelle que soit la srtatégie choisie, il faudra une bonne représentation de l’ensemble des trous
disponibles.
5.3.5.1 Bitmap
L’espace mémoire adressable est décomposé en blocs de taille 2n fixe. La partition allouée à
un processus est composée d’un nombre entier de blocs.
On définit une table (conservée en mémoire) dont chaque bit définit l’état (libre=0, oc-
cuppé=1) d’un bloc en mémoire.
Une fraction 1/2n+3 de la mémoire totale est donc occupée par la table.
1 1 1 0 0 0 0 1
1 1 1 1 1 1 0 0
0 0 0 1 1 1 1 1
0 0 1 1 1 0 0 1
1 1 1 0 0 0 0 1
0 0 0 0 0 0 0 1
!#"$ &%!' (*)+ , "$%!-. &/!01- 2 -32 4
5 607 8 8 9;:<9*=?> @ 5 9$5 AB>4C?9*=?D!8 >@$A E+F 9,8 6#G!60H537 537 >4=
IKJ4L MN3OP QSR3P QUT V#I!VWQN3L N L J4MXJ4PT OYN3QJ4P?R3PZL [0VMN
P 0 3 T 3 4 P 7 5 P 12 3
T 15 5 P 20 5 T 25 2 P 27 4
pas de compter les blocs occupés et libres. Ainsi on trouvera plusieurs segments P contigus, là
où le bitmap ne verra qu’un seul segment occupé.
Yann MORÈRE
5.4 La mémoire virtuelle 67 / 103
5.4.1.2 Segmentation
Comme dans le cas des structures de recouvrement, l’espace adresse du processus est expli-
citement décomposé par le programmeur en blocs logiques (données, code d’E/S, code d’initia-
lisation, calculs numériques, etc...) appelés segments. Il est important de noter que les segments
ne sont pas tous de la même taille (contrairement à ce que nous verrons avec la pagination).
On identifie les éléments dans un segment par leurs déplacements à partir du début du
segment. Un espace d’adresse logique est un ensemble de segments. Chaque segment possède
un nom et une longueur. Les adresses spécifient le nom du segment et le déplacement dans
ce segment. Chaque adresse est donc désignée par deux quantités : un nom de segment et un
déplacement. Pour des raisons de simplification les segments sont référencés par des numéros
de segments. Au final un adresse logique est définie par le doublet :
<numéro du segment, déplacement>
Un prérequis pour la segmentation est donc bien évidemment que le code généré soit (au
minimum) relogeable.
La transformation des adresses logiques en adresses physiques s’effectuent à l’aide d’une
table des segments, comme montré sur la figure 5.9.
N!O1N
P*QR'SSUTWVEP*QRX P TYTZP\[!T^] _ TQ QT`GQ[_ R[GQTa a*R'bT
Fig. 5.9 – Transformation d’une adresse logique en adresse physique dans le cas de la mémoire
segmentée
Yann MORÈRE
5.4 La mémoire virtuelle 69 / 103
Si le nombre de segments est faible, la table des segments sera le plus souvent conservées
dans des registres. Sinon, une partie de la RAM sera utilisée à cette effet. La table des segments
fait bien entendu partie des informations sur un processus que le système d’exploitation doit
préserver lorsque le processus élu est désactivé et rétablir lorsqu’un nouveau processus prend
le contrôle de l’UCT.
De manière plus générale, contrairement au cas des structures de recouvrement, le système
d’exploitation est en charge des segments.
Les principaux avantages de la segmentation sont :
¤ elle élimine pratiquement le problème de fragmentation interne et reduit le problème de
la fragmentation externe,
¤ elle permet une gestion fine et fonctionnelle de la gestion mémoire,
¤ elle permet de partager la totalité ou des parties du code entre plusieurs processus et de
protéger les accès à ces segments.
Les principaux inconvénients de la segmentation sont :
¤ les segments doivent être définis explicitement par le programmeur,
¤ elle n’élimine pas complètement le problème de la fragmentation externe,
¤ les segments sont de taille variable et la gestion des allocations de trous reste aussi
complexe que dans le cas des partitions contigües.
5.4.1.3 Pagination
lespace adresse du processus est découpé en morceaux de petite taille fixe (pour le système),
ou pages qui occupent des cadres de page (frames) en mémoire.
La taille des pages est un paramètre d’environnement du système d’exploitation. Il est fixé
à l’initialisation du système et ne peut changer en cours dexécution. Typiquement, cette taille
est une puissance de 2 : p = 2n, (le plus souvent, de 512 octets à 8 K = 8192 octets). De cette
façon, si la taille de l’espace adressable est 2m, alors les mn premiers bits de l’adresse logique
indiquent le numéro de page et les n bits suivants indiquent le déplacement (offset) à l’intérieur
de cette page.
Fig. 5.10 – Pagination : décomposition de l’espace d’adresse d’un processus en pages de taille
fixe
Les coupures entre deux pages consécutives peuvent se produire à des endroits arbitraires
dans l’espace adresse : au milieu dune instruction en langage machine, de données, etc.
En pratique, les frontières entre blocs de types différents (code, données statiques, pile,
monceau) sont toutefois généralement respectées.
Plusieurs solutions, chacune ayant ses avantages, ont été proposées pour implanter la liaison
(binding) entre les adresses logiques et les adresses en mémoire paginée. La plus simple nutilise
qu’une table de pages.
Dans la mesure où la taille des cadres est relativement réduite, un processus nécessite gé-
néralement un grand nombre de pages. Il est donc le plus souvent impossible de conserver la
totalité de la table de pages dans des registres. Il en résulte un important ralentissement des
accès à la mémoire.
On peut combiner les avantages de rapidité d’accès et de grands nombres de pages (grandes
partitions pour les processus) en utilisant des registres associatifs (translation look-aside buffers
ou TLBs).
Yann MORÈRE
5.4 La mémoire virtuelle 71 / 103
On va utiliser une table principale (outer page table) pour accéder à la table de pages
(elle-même paginée) qui contient les numéros de cadres.
La première moitié du numéro de page, p1, est utilisée pour trouver dans la table principale
le numéro de la page dans la page de tables qui contient lentrée pour p2, cest-à-dire le numéro
de cadre en mémoire physique. Finalement, le déplacement d est appliqué.
Avantage de cette technique : Comme la page de tables est elle-même paginée, elle n’a
plus besoin d’occuper un bloc contigu en mémoire.
De nos jours, la plupart des microprocesseurs supportent trois voire quatre niveaux de pagi-
nation. Afin de ne pas trop dégrader les temps daccès à la mémoire, la pagination à plusieurs
niveaux est toujours utilisée en conjonction avec des registres associatifs (TLB). Les calculs que
nous avons faits pour un niveau de pagination se généralisent sans peine à plusieurs niveaux.
Les principaux avantages de la pagination sont que :
¤ Elle est complètement transparente pour le programmeur qui n’a pas besoin de définir
explicitement la décomposition et peut ne se soucier que de son espace mémoire logique
contigu.
¤ Elle permet de partager du code ré-entrant entre plusieurs processus (en particulier après
un fork()).
¤ Elle permet un bon niveau de protection de la mémoire.
Elle élimine pratiquement les problème de fragmentation interne et de fragmentation externe.
Les principaux inconvénient de la pagination sont que :
¤ Comme elle est effectuée de manière aveugle, selon une taille de page fixe, les coupures
entre pages ne sont pas toujours judicieuses.
¤ Le programmeur qui souhaite un degré de contrôle très fin de l’exécution de son code
aura beaucoup plus de mal à le faire que dans le cas de la segmentation.
¤ Contrairement à la segmentation, il nest pas possible de distinguer différentes parties du
code qui peuvent être partagées par différents processus : cest le code en entier qui est
partagé.
¤ Il faut créer une table de pages pour chaque processus qui est chargé dans le système.
Malgré ces inconvénients, la pagination est de loin la technique la plus utilisée de nos jours par
les systèmes de gestion de la mémoire (Memory Management Unit ou MMU).
Yann MORÈRE
5.4 La mémoire virtuelle 73 / 103
programme dispose d’un bloc contigu en mémoire, alors que l’espace adresse de son programme
est effectivement disséminé en pages occupant des cadres en mémoire physique.
Nous venons également de voir comment la partition d’un processus chargé dans le système
peut être transférée entre la mémoire principale et la mémoire secondaire afin de permettre
d’augmenter le degré de multiprogrammation du système.
L’étape suivante consiste à se demander si, lorsque la partition dun processus est chargée
en mémoire (swap in), toutes les pages ont effectivement besoin dêtre présentes en RAM.
¤ Un lazy swapper ne charge une page en mémoire que si elle est effectivement nécessaire
(demandée).
En fait, le terme swapper n’est pas approprié quand on parle du chargement/déchargement
de pages individuelles, car un swapper manipule des partitions entières. On emploiera donc le
terme pager dans le contexte de la demande de page.
Si seulement un sous-ensemble des pages dun processus est effectivement présent dans des
cadres de pages, il se produira de temps à autre, au cours de l’exécution de ce processus, une
faute de page, (page-fault) cest-à-dire une demande d’accès à une page qui n’est pas présente
dans un cadre de page.
Traitement d’une faute de page durant l’exécution d’un processus P :
1. Il se produit une trappe matérielle (hardware trap) vers le kernel. Le compteur programme
et éventuellement l’état de l’instruction courante du processus interrompu sont préservés
dans une pile
2. Une routine (généralement écrite en langage dassemblage) est exécutée qui sauvegarde les
registres et appelle le kernel qui prend alors le contrôle de lUCT.
3. Le kernel découvre qu’une faute de page s’est produite, et sur quelle page virtuelle cette
faute sest produite.
4. Le gestionnaire de la mémoire virtuelle vérifie si la page est valide et si le processus P a
le droit d’accéder à cette page.
5. Si la page à tuer avait été modifiée, elle doit être écrite dans lespace de swap (sur disque).
Elle est marquée busy jusqu’à ce que lopération d’E/S soit terminée.
6. Un changement de contexte se produit. Le processus P est bloqué en attente dE/S (lecture
dune page et éventuellement écriture dune autre), son PCB du est préservé, et un nouveau
processus est activé.
7. Pendant que l’UCT traite d’autres processus, les E/S de pages s’effectuentet la table de
pages est remise à jour. P revient à l’état prêt.
8. Quand P revient à l’état élu, le PCB et l’intruction ayant causé la faute de page sont
rétablis et l’exécution reprend.
Yann MORÈRE
5.4 La mémoire virtuelle 75 / 103
T = (1 − p) × (80ns) + p × (20ns)
= 80 + 19.999.920p
5.4.7.1 PAPS
L’algorithme le plus simple : lorsqu’une faute de page se produit, c’est la page qui occupe
depuis le plus longtemps un cadre de page qui est tuée.
Nous obtenons donc avec cette séquence un total de 12 fautes de pages. La ligne marquée
LRU contient le classement de plus récente utilisation. La page en bas de cette liste doit être
la prochaine victime si une faute de page se produit.
L’inconvénient principal de LRU est son implantation qui nécessite le classement des pages
selon leur dernière référence.
Yann MORÈRE
5.4 La mémoire virtuelle 77 / 103
faible. Après un certain temps, cette inertie finira par être vaincue (si le processus conserve la
même localité assez longtemps), mais il en résulte un nombre important de fautes de pages.
On a aussi proposé lutilisation des algorithmes suivants, qui ne se sont pas avérés bien
efficaces :
¤ LFU (Least Frequently Used),
¤ MRU (Most Recently Used).
Nous obtenons cette fois ci 10 fautes de pages, bien que le nombre de cadres soit plus grand !
C’est l’anomalie de Belady.
Nous obtenons donc un total de 6 fautes de pages. Cest le plus petit nombre possible avec
4 cadres de pages et cette séquence.
Yann MORÈRE
5.4 La mémoire virtuelle 79 / 103
¤ Le bit de référence indique si une demande d’accès à la page (en lecture ou en écriture)
a eu lieu depuis la dernière vérification et remise à zéro de ce bit. Ce bit est remis à 1
par le MMU lors de chaque accès à la page.
¤ Le bit dirty indique si le contenu de la page a été modifiée, cest-à-dire s’il diffère du
contenu de l’image conservée sur disque.
¤ Le bit de protection indique si le contenu de la page peut être modifié (en général, ce bit
est à 0 pour une page de code).
¤ Le bit de présence indique si la page occupe présentement un cadre de page.
Chapitre 6
Interblocage
Yann MORÈRE
6.1 Introduction : définition et caractérisation 83 / 103
Une ressource est représentée par une boı̂te rectangulaire. S’il existe plusieurs instances
indifférentiables de la ressource, on les représente dans la même boı̂te.
Par indifférentiable, on entend qu’un processus ne devrait pas pouvoir choisir une instance
de cette ressource plutôt qu’une autre : il prend la première disponible. Dès lors qu’un processus
peut choisir une instance plutôt qu’une autre, elles sont différentiables, et on les modélisera alors
comme des instances de ressources différentes.
Un arc émanant d’une instance d’une ressource R et pointant vers un processus signifie que
cette instance de R est détenue par P.
Un arc émanant d’une processus P et pointant vers une ressource R signifie que P est bloqué
en attente d’un instance de ressource de type R.
Dans l’état représenté à la figure 6.4, le processus P1 détient la seule instance de la ressource
RB et est bloqué en attente de RA, que détient P2. Le processus P2 lui-même détient une
instance de la ressource RC mais il est bloqué en attendant qu’une seconde instance se libère,
ce qui ne pourra se faire que lorsque P3 , qui détient 3 instances de RC en libèrera une. Si à ce
point de son exécution P3 venait à demander une ressource de type RB, on obtiendrait alors le
graphe suivant, qui correspond à un état d’interblocage :
6.1.4 Remarques
Pour des raisons évidentes, le graphe ci-dessous correspond à un état impossible : si les
instances de RC sont effectivement indifférentiables, alors P2 ne devrait pas pouvoir être bloqué
en attente de RC alors qu’un instance de cette ressource est libre.
La présence d’un cycle dans le graphe d’allocation de ressources est une condition nécessaire
pour que l’état courant corresponde à un interblocage. Si chacune des ressources impliquées dans
le cycle compte une seule instance, alors cette condition est aussi suffisante. Les figures suivantes
illustrent cette remarque.
Pour qu’il y ait interblocage, il faut qu’il y ait blocage des processus impliqués, chacun
en attente d’une ressource que détient l’un des autres processus, comme par exemple dans le
graphe d’allocation de ressources ci-dessous.
Yann MORÈRE
6.1 Introduction : définition et caractérisation 85 / 103
De ce graphe d’allocation de ressources, on peut déduire le graphe indiquant qui attend qui,
et dans lequel on distingue aisément quelques cycles :
On pourrait faire de même pour une situation où l’on a plusieurs ressources de chaque type :
Yann MORÈRE
6.2 Vagabondage théorique sur linterblocage 87 / 103
3. la détection/résolution,
4. la stratégie de lautruche (ne rien faire).
Nous allons considérer dans les sections suivantes les motivations pour chacunes de ces approches
ainsi que les techniques qui ont été développées pour les mettre en application. Nous ferons
cela par le biais dun vagabondage à travers un certains nombre de concepts de la théorie de
l’informatique.
Afin de simplifier la discussion qui suit, nous supposerons que chaque processus effectue ses
requêtes d’allocation de ressources en faisant appel à une procédure similaire au Down() que
nous avons vu au chapitre 2. Autrement dit, lorsque le processus P demande 2 ressources de
type RA, 1 de type RB et 3 de type RC : Si toutes ces ressources sont disponibles et que le SE
les lui alloue, il peut continuer son exécution. Si elle ne sont pas toutes disponibles ou si le SE
ne lui en alloue quune partie, le processus P bloque en attendant que les ressources dont il avait
fait la requête lui soient accordées. Nous pouvons donc maintenant par exemple considérer que
les files dattente dE/S (resp. la file dattente des processus prêts) du chapitre 2 contiennent les
processus qui ont fait une demande dallocation de ressource de périphérique dE/S (resp. daccès
à lUCT) qui na pas pu être satisfaite.
Revenons un peu sur la signification des arcs dun graphe d’allocation des ressources, et
considérons pour ça le cas plus simple de la figure 10. Ce qui est important dans la figure 10
est qu’un arc partant d’un processus et allant vers une ressource nindique pas que le processus
va avoir besoin tôt ou tard de cette ressource, mais qu’il l’a déjà demandée et qu’il est bloqué
en attendant quelle lui soit allouée.
Yann MORÈRE
6.2 Vagabondage théorique sur linterblocage 89 / 103
On voit que tous les processus, sauf P3, sont bloqués. Il ny a malgré tout pas encore d’in-
terblocage. Autrement dit, si P3 termine son exécution normalement, il libèrera ses ressources,
et P2, P6 et P8 pourront reprendre leur propre exécution là où elle avait été interrompue (sur
une demande d’allocation de ressources). Si maintenant P3 demande une ressource de type Ph,
cette demande ne peut pas être satisfaite, P3 bloque, et l’on aboutit à l’état d’interblocage qui
avait été représenté à la figure 6.7.
En résumé : Le graphe d’allocation des ressources est uniquement un bon indicateur de l’état
courant du système processus + ressources. Il nous donne une vue instantanée de l’état de
chaque processus : bloqué (ce que nous avons appelé jusquà présent en attente) ou actif
(prêt ou élu). De même, il nous donne une vue instantanée de chaque instance de chaque
ressource (allouée ou libre), mais il ne nous donne aucune indication sur le futur de ce
système. En particulier, il ne nous informe en rien sur les besoins des processus : il ne nous
dit pas de quelles ressources un processus donné va devoir faire une requête. A fortiori, il
ne nous dit rien sur la chronologie de ces requêtes. L’état représenté à la figure 6.10 ne
pose un problème que si P3 demande une ressource qui est déjà allouée. Autrement dit,
si on savait à l’avance de quelle ressources P3 va faire la demande, on pourrait décider si
cet état doit être évité ou pas. La question que l’on peut se poser est : Est-il possible de
déterminer à l’avance les besoins des processus en matière d’allocation de ressources ?
Le problème est qu’un tel module de prédiction est impossible. Il fait en effet partie de
la classe de problèmes dont on peut prouver qu’il ne sont pas calculables (ou décidables).
Autrement dit, il n’existe pas d’algorithme qui soit capable de faire ce genre de chose. Notez
bien que l’on dit bien ”il n’existe pas”, et non pas il n’existe pas encore. Tous ces problèmes
indécidables se ramènent au problème de l’arrêt (halting problem) pour lequel il est facile de
prouver qu’il nexiste pas de solution algorithmique. Le problème de l’arrêt dit à peu près la
chose suivante :
¤ Il n’existe pas d’algorithme capable de prendre comme paramètres le code d’un pro-
gramme P et des entrées pour ce programme, et de décider si P terminera normalement
sur ces entrées ou pas (auquel cas, on supposera quil boucle à l’infini). N.B. Il est im-
portant que le code de P fasse partie des entrées. Il est bien évident que l’on pourrait
effectuer de manière automatique une telle vérification des données pour un programme
P spécifique.
Yann MORÈRE
6.2 Vagabondage théorique sur linterblocage 91 / 103
ne connaı̂t pas encore la réponse à la question), mais il est de toute façon trivial (fonction
constante).
N.B. : Nous ne traiterons ici que des fonctions/programmes à une seule entrée et une seule
sortie. La généralisation à n entrées et p sorties est triviale. Nous allons chercher à éta-
blir une liste indexée complète de tous les programmes Pascal possibles (nous aurions pu
prendre C, mais Pascal est un langage plus propre qui se prête mieux à ce genre d’ana-
lyses). Nous procédons de la manière suivante : Soit un entier n. Nous convertissons n
en sa forme binaire qui nous décomposons en octets, puis, à chaque octet, nous associons
le caractère dont il est le code ASCII. Nous obtenons donc, pour tout nombre n, le code
source d’un programme Pascal (ce programme peut être correct comme il peut ne pas
l’être).
Si les caractères correspondant à n ne forment pas le code d’un programme Pascal syntaxique-
ment correct (qui ne compile pas), on associe à n le programme suivant (boucle infinie) :
begin read(X) ;
while X = X do
Y := X ;
write(Y) ;
end.
Nous avons défini une correspondance entre l’ensemble des nombres entiers naturels et celui
de tous les programmes PascaL, et nous disposons donc maintenant d’une liste exhaustive de
tous les programmes Pascal : P1, P2,..., Pn,... Nous pouvons alors énoncer le théorème suivant :
Théorème (problème dit de l’arrêt) : Il n’existe pas de programme P capable de décider, pour
tout nombre n, si le programme Pn terminera (correctement) si on lui soumet n comme entrée.
Démonstration (par labsurde) Supposons quun tel programme existe, et appelons-le Ar-
rêt(X). Ce programme implante la fonction suivante : f (x) = 1, si Px termine quand on lui
soumet x comme entrée, 0, sinon ( Px plante si on lui soumet x comme entrée). On peut par
conséquent définir le programme Confondre(X)suivant :
begin read(X) ;
Y := 1 ;
if Arr^
et(X) <> 0 then
while Y <> 0
do Y := Y ;
write(Y) ;
end.
Ce programme implante la fonction y suivante : y (x) = 1, si f (x) = 0, non définie, sinon
(plante si on lui soumet x comme entrée).
Par conséquent (en résumé), si le programme Arrêt(X) existe, alors le programme Confondre(X)
est défini, et il existe un nombre entier naturel e tel que Pe = Confondre(X). La question que
l’on se pose alors est : que retourne Pe si on lui soumet e comme entrée, c’est-à-dire, que vaut
y (e) ? Si y (e) = 1), cela signifie que Arrêt(e) = 0, et donc que Pe (Confondre) ne termine pas si
on lui soumet e comme entrée, et donc que y (e) est indéfini, ce qui constitue une contradiction.
Si y (e) est indéfini, cela signifie que Arrêt(e) = 1, et donc que Pe (Confondre) termine si on lui
soumet e comme entrée, et donc que y (e) termine correctement, ce qui constitue une contra-
diction. Nous avons dans les deux cas une contradiction. Le programme Arrêt(X) ne peut donc
pas exister.
De manière générale, ce qu’il faut retirer de cette longue parenthèse théorique est qu’il nest
pas possible de prédire de manière automatique et à l’avance le comportement d’un programme
à partir de son code et des données qui lui sont soumises. On peut par contre déveloper des
Nous venons de voir qu’il n’était pas possible de prédire à l’avance quels seraient les besoins
en ressources d’un processus donné (pour une certain vecteur d’entrée de paramètres). Nous
nous replions donc sur une version plus faible de ce problème : Supposons que l’on dispose,
pour chaque processus présent dans le système de la séquence ordonnées de ses demandes et
libérations de ressources. Étant donné un état initial du système, est-il possible de déterminer
s’il existe un ordonnancement de ces processus (autrement dit, la façon dont on leur alloue le
temps UCT) tel que l’on évite tout interblocage ?
Autrement dit, si on pouvait (par des processus incantatoire impliquant le sacrifice de petits
animaux pelucheux) parvenir à prédire le résultat de la boite noire de la figure 6.14, saurait-on
comment esquiver les interblocages (faire en sorte quils ne se produisent pas) ?
Fig. 6.15 – On suppose que lon dispose dune chronologie des demandes de ressources
Malheureusement, même sous cette forme simplifiée, le problème reste trop complexe. Cette
fois-ci, il existe bien un algorithme qui trouvera une solution, mais sa complexité algorithmique
est trop élevée. Rappel : On dira qu’une fonction f (n) est d’ordre O (g (n)) s’il existe un entier
N et un réel c > 0 tel que, pour tout n > N , on ait : f (n) > c × g (n). Il est à noter que la
notion de complexité algorithmique est de nature asymptotique : elle ne décrit pas ce qui se
passe pour de petites valeurs de n (voir figure 6.16).
Yann MORÈRE
6.2 Vagabondage théorique sur linterblocage 93 / 103
Dans le cas d’un algorithme P admettant n entrées (points, nombres, mots, etc.), la com-
plexité algorithmique de P est la fonction f faisant correspondre à la taille de l’entrée n le
nombre d’opérations élémentaires nécessaire à l’exécution de P .On dira alors par abus de lan-
gage que P est de complexité algorithmique O (g (n)) si et seulement si la fonction f (n) est
d’ordre O (g (n)).
Fig. 6.18 – Effet de progrès technologiques sur la taille du plus grand problème traitable en 1
heure de calcul.
Après avoir lu ce préambule, on s’attend sans doute à lire ici que la complexité des algo-
rithmes classiques d’esquive de l’interblocage est mauvaise (élevée). La situation est en fait
bien pire que ça : le problème d’esquive de l’interblocage en version simplifiée à partir de la
chronologie ”devinée” est NP-complet.
Autrement dit (en trivialisant ce-faisant vraiment beaucoup la notion de problème NP-
complet), non seulement personne ne connaı̂t de solution algorithmique à ce problème qui ait
une complexité polynomiale (de type n2 ou n3 , où n serait par exemple le nombre de de-
mandes/libérations de ressources), mais il est fort à douter qu’un tel algorithme existe. En fait
il existe une classe de problèmes, dits NP-complets, qui couvrent par exemple des problèmes
de réseaux (avec application en informatique et en téléphonie), de gestion de ressources, d’or-
donnancement, de logique (diagnostic de systèmes). Tous ces problèmes peuvent être ramenés
de l’un à l’autre, ce qui veut dire que si un jour quelqu’un trouve une solution polynomiale à
l’un de ces problèmes, alors cela signifiera que tous les autres ont une solution algorithmique
de complexité algorithmique polynomiale. En attendant, personne ne retient son souffle....
Yann MORÈRE
6.2 Vagabondage théorique sur linterblocage 95 / 103
Pour avoir une image complète de l’état du système vis-à-vis de l’utilisation de ses ressources,
il nous faut encore préciser le nombre total d’instances de chaque ressource dans le système
Nombre total d’instances de chaque type de ressource dans le système
Nous reprenons ici l’exemple du manuel de Tannenbaum (pp. 252–254). Nous considérons
deux processus, P0 et P1 , qui doivent partager l’accès à deux ressources : une table traçante T
et une imprimante I. La figure 6.20 donne un exemple de séquence d’allocation/libération de
ces deux ressources par les deux processus (dont on donne le pseudo-code déroulé).
La possibilité d’interblocage survient lorsque les deux processus exécutent de manière concu-
rente et que leurs besoins de ressources sont en conflit. La figure suivante donne l’ensemble des
possibilités de scénarios.
Yann MORÈRE
6.3 Solutions au problème de l’interblocage 97 / 103
Fig. 6.21 – Séquencements possibles des allocations et libérations de ressources pour les deux
processsus.
moins une séquence d’allocation de ressources aux processus permettant déviter l’interblocage.
Afin déviter que ne se produise un interblocage, il suffit donc, lorsqu’un processus présente au
système une demande d’allocation de ressource, de vérifier si le nouvel état obtenu serait un
état risqué. Si c’est le cas, il faut refuser la ressource au processus (qui va donc bloquer en
attente de cette ressource). Sinon, le processus obtient la ressource.
Yann MORÈRE
6.3 Solutions au problème de l’interblocage 99 / 103
est normal). En premier lieu, il est bien évident que pour qu’un processus participe à un inter-
blocage, il qu’il soit bloqué. Par conséquent, l’algorithme de détection d’interblocage que nous
allons voir ne doit prendre en compte que les processus bloqués en attente d’une ressource, et
donc ignorer le(s) processus élu(s) ainsi que les processus présents dans la file d’attente de bas
niveau. D’autre part, dès lors qu’il existe plusieurs instances de ressources, il ne suffit pas de
détecter des cycles dans le graphe d’attente (figures 4.8 à 4.11). Il faudra utiliser un algorithme
plus complexe s’apparentant à l’algorithme du banquier.
Ici encore, il va donc falloir supposer que l’on connaı̂t à l’avance les besoins maximaux
de ressources de chaque processus, ce qui nous permet d’utiliser les matrices d’allocation de
ressources. Construire la liste L des processus bloqués.
répéter
1. Chercher, parmi tous les processus sur L, s’il est un processus P dont les besoins (nombre
d’instances de ressources requises) peuvent être satisfaits (inférieurs au nombre dinstances
de ressources disponibles).
2. Si P existe, alors on lui accorde les ressources dont il a besoin et on le fait terminer. S’il
existait plusieurs choix pour P , peu importe celui que l’on choisit, vu que l’on dispose
de plus de ressources après que l’on ait fait terminer un processus. On obtient un nouvel
état du système.
jusqu’à ce quil ny ait plus de processus P pouvant terminer. S’il reste des processus sur L, alors
ils participent à un interblocage.
Yann MORÈRE
6.3 Solutions au problème de l’interblocage 101 / 103
se voir retirer des ressources. Le problème dans ce cas est bien entendu le compromis à établir
entre la fréquence souhaitable des sauvegardes d’état et la performance globale du système.
Bibliographie
[Carrez, 2000] C. Carrez. Les systèmes informatiques : Vision cohérente et utilisation. 2000.
[Hervé et al., 1999] J.Y Hervé, K. Titus, et S. Drouin. Systèmes d’exploitation. 1999.
[Silberschatz et Galvin, 1994] A. Silberschatz et P.B. Galvin. Principes des systèmes d’exploi-
tation. 4 édition, 1994.