Vous êtes sur la page 1sur 179

Systèmes d’Exploitations Avancés

Chapitre VI :
Gestion de la mémoire
Amine DHRAIEF

Mastère professionnel en Modélisation, Bases de


Données et Intégration des Systèmes

ESEN, Univ. Manouba


Introduction

Les programmes s’accroissent pour


remplir la mémoire disponible qui leur
est réservée
12/15/16 2
Introduction
• Souhaits des programmeurs
– Une mémoire infiniment grande
– Une mémoire infiniment rapide
– Non volatile
– Bon marché !
– Frein technologique → hiérarchie de la mémoire

• hiérarchie de la mémoire
– Quelques MB de mémoire cache volatile, rapide et chère
– Quelques GB de mémoire rapidité moyenne, prix moyen
– Quelques TB de mémoire non volatile, lente, mémoire de
masse

12/15/16 3
Introduction

• Gestionnaire de la mémoire :Entité


du S.E qui gère hiérarchie de la
mémoire
– Garde trace de la partie de la mémoire qui est
en cours d’utilisation et celle qui ne l’est pas
– Allouer de la mémoire au processus
– Libérer la mémoire à la fin de l’exécution des
processus

12/15/16 4
Abstraction de la mémoire ?
• Avant 1980: on ne disposait pas d’abstraction
– MOV REGISTER1, 1000
– on fait passer le contenu de l’emplacement mémoire 1000 dans
le registre REGISTER1
– Il n’était pas possible d’exécuter deux programmes en même
temps

• Le modèle de mémoire présenté au programmeur


correspondait tout simplement à la mémoire physique
– Un ensemble d’adresse numérotées de 0 à une valeur maximale
– Chaque adresse désignant une cellule contenant un certain
nombre de bit (8 bits)

12/15/16 5
Abstraction de la mémoire ?

• Même si le modèle ne reflète que la mémoire physique, il peut exister


plusieurs variantes
– (a) S.E en bas de la mémoire vive RAM (n’est plus utilisé)
– (b) S.E en haut de la ROM (système embarqué)
– (c) gestionnaire des périphérique en haut de la ROM (BIOS), S.E en RAM
(MSDOS)

• Le modèle (c) représente un inconvénient majeur: un bogue dans un


programme utilisateur peut engendrer des conséquences
désastreuse sur le S.E.

12/15/16 6
Abstraction de la mémoire ?
• Un seul processeur peut s’exécuter à la fois. Dès
que l’utilisateur tape une commande
– Le S.E copie le programme demandé depuis le
disque vers la mémoire et l’exécute
– Lorsque le processus se termine, le S.E affiche le
prompt et attend une nouvelle commande
– Quand il reçoit la commande, il charge un nouveau
programme en mémoire en écrasant le précédent

12/15/16 7
L’exécution de plusieurs programmes
sans abstraction de mémoire
• Même sans abstraction de la mémoire, il est
cependant possible d’exécuter quasi
simultanément plusieurs programmes.

• Le S.E. doit alors recopier sur disque


l’intégralité du contenu de la mémoire avant
de charger et d’exécuter le programme suivant

• C’est le va-et-vient ou swapping

12/15/16 8
UNE ABSTRACTION DE LA MÉMOIRE:
LE ESPACES D’ADRESSAGE

12/15/16 9
Contexte
• Faire voire aux processus la mémoire physique
présente plusieurs inconvénients
– Risque de plantage générale, même avec un seul
programme qui s’exécute
– Lourdeur pour exécuter plusieurs programmes à la
fois

• Besoin d’abstraction de la mémoire

12/15/16 10
La notion d’espace d’adressage

• De la même façon qu’un processus crée une


UC abstraite exécutant un programme, l’espace
d’adressage est une sorte de mémoire abstraite
d’un programme prêt à l’exécution

• C’est l’ensemble des adresses qu’un processus


peut utiliser pour adresser la mémoire

• Chaque processus a son propre espace


d’adressage, indépendant de celui des autres

12/15/16 11
La notion d’espace d’adressage

• Il est difficile de donner à chaque


programme son propre espace
d’adressage
– C’est-à-dire de faire en sorte que l’adresse
(abc) de l’un correspond à un emplacement
différent de l’adresse (abc) de l’autre

• Solution: ré-allocation dynamique

12/15/16 12
La notion d’espace d’adressage

12/15/16 13
Les registres de base et de limite

• Ré-allocation dynamique: mapper l’espace


d’adressage de chaque processus sur une
partie différente de la mémoire physique.

• Équiper les UC de deux registres matériels:


les registres de base et de limite.
– Les programmes sont chargés en mémoire sans
ré-allocation, là où il y a de la place pour les ranger
dans des mots mémoire consécutifs

12/15/16 14
Les registres de base et de limite

• À l’exécution du programme, le S.E


range dans le registre de base
l’adresse physique de début de
programme et dans le registre de limite
et celle de fin
– Les valeurs de base et de limite du premier
programme sont de 0 et 16384 (16Ko x 1024
= 16384)
– Du second programme 16384 et 32768

12/15/16 15
Les registres de base et de limite

• Chaque fois qu’un processus référence


la mémoire,
– que ce soit pour charger une instruction ou bien
lire ou écrire une donnée,
– le matériel de l’UC ajoute automatiquement à
l’adresse engendrée par le programme la valeur
du registre de base
– et vérifie la nouvelle adresse ainsi créée reste
bien inférieur ou égale à la valeur du registre de
limite
12/15/16 16
Les registres de base et de limite

• Dans le cas de la première instruction du second


programme exécute une instruction
– JMP 10

• Le matériel la traite comme si c’était


– JMP 16394
– 16394 = 16384 +10

• L’inconvénient majeur de cette méthode est qu’elle


exige une addition et une comparaison à chaque
référence mémoire
12/15/16 17
Le va-et-vient (swapping)

• Si la mémoire physique de l’ordinateur est


suffisamment grande pour contenir tous les
processus, les méthodes vues jusqu’ici
conviennent.
– En pratique, c’est rarement le cas
– Sur les S.E. actuelles, entre 40 et 60 processus sont
lancés au démarrage
– Sous windows, un processus de vérification de mise à
jour d’une application, lancée au démarrage occupe
entre 5 et 10 Mo!
– Firefox peut occuper facilement 270Mo de mémoire

12/15/16 18
Le va-et-vient (swapping)

• Deux approches de gestion de


mémoire peuvent être utilisées
– Le swapping: considérer chaque processus
dans son intégralité, exécution puis
placement sur le disque
– La mémoire virtuelle: permet au
programmes de s’exécuter même quand ils
sont partiellement en mémoire principale

12/15/16 19
Le va-et-vient (swapping)

• L'allocation de la mémoire change au gré des processus


qui viennent en mémoire et ceux qui quittent la mémoire

• Les zones grises indiquent la mémoire non utilisée


12/15/16 20
Le va-et-vient (swapping)
i. (a) A est en mémoire

ii. (b,c) B et C sont crées


ou chargés depuis le
disque

iii. (d) A est transférer sur le


disque

iv. (e,f) D arrive, tandis que


B s’en va

v. (g) A revient
12/15/16 21
Le va-et-vient (swapping)

• Lorsque le swapping crée de multiples trous


dans la mémoire, il est possible de tous les
recombiner en une seule zone plus grande en
déplaçant tous les processus vers le bas de
la mémoire aussi vite que possible
– Compactage de mémoire

• N’est pas mise en œuvre car elle requiert


énormément de temps UC
– 5s pour compacter 1 Go!
12/15/16 22
Le va-et-vient (swapping)
• Si des processus sont crées avec une taille fixe qui
ne change jamais, l’allocation est alors simple: le
système alloue exactement la mémoire nécessaire
pas plus pas moins !

• Lorsque les segments de données des processus


doivent croître (allocation dynamique de la mémoire)
un problème surgit toutes les fois qu’un processus
essaie de s’accroître.
– Si un trou est adjacent au processus, ce trou peut lui être
alloué et le processus est autorisé à s’étendre dedans

12/15/16 23
Le va-et-vient (swapping)
• Si le processus est adjacent à un autre processus, le
processus croissant devra être déplacé dans un trou
suffisamment grand pour lui

• Si un processus ne peut pas croître en mémoire et que


la zone de va-et-vient sur le disque est pleine, le
processus devra attendre ou être tué
– Il est conseillé d’allouer un ‘peu’ de mémoire supplémentaire
chaque fois qu’un processus est chargé ou déplacé
– Si on transfert le processus sur le disque, seule la mémoire
véritablement utilisé qui doit être recopiée, inutile de recopier
la mémoire supplémentaire.

12/15/16 24
Gérer la mémoire libre

• Quand la mémoire est attribué


dynamiquement, le système
d’exploitation doit la gérer

• Il existe deux manière de conserver


une trace de l’utilisation de la mémoire
– À l’aide des tables bits
– À l’aide des listes

12/15/16 25
Gérer la mémoire avec une table de
bits
• Avec une table de bits, la mémoire est
répartie en unités d’allocation dont la
taille peut varier de quelques mots à
plusieurs kilo-octets.

• Chaque unité d’allocation correspond à


un bit du tableau de bits, lequel est 0 si
l’unit correspondante est vide et 1 si elle
est occupée (ou vice versa)
12/15/16 26
Gérer la mémoire avec une table de
bits

a) Une partie de la mémoire avec 5 processus, 3 trous


Les petites marques verticales indiquent les unités
d'allocation
Les zones grises sont libres
b) Le tableau de bits correspondant
c) Mêmes informations sous la forme d'une liste chaînée
12/15/16 27
Gérer la mémoire avec une table de
bits
• La taille de l’unité d’allocation est un élément
fondamentale dans la configuration:
– plus l’unité est petite, plus le tableau de bit est
important

• Avec une unité de 4 octets (32bits), n’auront


besoin que de 1 bit du tableau de bit
– Une mémoire de 32n bits utilisera une table de n
bits qui ne prendra pas plus de 1/33 de la mémoire

12/15/16 28
Gérer la mémoire avec une table de
bits
• Le tableau de bit offre un moyen simple de
garder une trace des mots mémoire dans
une quantité fixe de mémoire

• Le tableau offre un inconvénient:


– lorsqu’un processus de k unités est chargé en
mémoire, le gestionnaire de mémoire doit
parcourir le tableau de bits pour trouver une
séquence de k bit consécutifs dont la valeur est
0.
12/15/16 29
Gérer la mémoire avec des listes
chaînées
• Une des manière de conserver une trace de la
mémoire est de maintenir une liste chaînée des
segments de mémoire alloués et libres
– Dans cette liste, un segment est soit un processus, soit un
trou entre deux processus
– La liste est trié par adresse, donc si un processus se
termine la mise à jour est directe

12/15/16 30
Gérer la mémoire avec des listes
chaînées
• Un processus qui se termine a normalement deux
voisins (excepté en début de liste/fin de liste) qui
peuvent être des processus ou des trous, ce qui
conduit à quatre combinaison possibles

12/15/16 31
Gérer la mémoire avec des listes chaînées
• (a) la mise à jours de la liste
oblige à remplacer un P par un T

• (b,c) deux unités sont réunies


en une seule, la liste devient
plus courte d’une unité

• (d) trois entrées sont fusionnées


et deux items sont retirés de la
liste

• → Il y a avantage a utiliser une


liste de segments doublement
chaînée afin de faciliter la
recherche du nœud précédent.

12/15/16 32
Gérer la mémoire avec des listes
chaînées
• Quand les processus et les trous sont indiqué
dans une liste triées par adresse, plusieurs
algorithmes peuvent servir à allouer de la
mémoire à un processus nouvellement créé (ou
un processus existant chargé depuis le disque)
– First fit
– Next fit
– Best fist
– Worst fit
– Quick fit

12/15/16 33
Gérer la mémoire avec des listes chaînées
First Fit

• Algorithme de la première zone libre:


– On trouve le premier trou suffisamment grand
pour contenir le processus.
– Le trou est ensuite divisé en deux parties: une
pour le processus et l’autre pour la mémoire
inutilisée

• Algorithme rapide parce qu’il limite ses


recherches autant que possible
12/15/16 34
Gérer la mémoire avec des listes chaînées
Next Fit

• Algorithme de la première zone libre


suivante

– Identique à l’algorithme précédent sauf que la


recherche commence au dernier espace libre
trouvé.

– Les performance sont légèrement meilleures

12/15/16 35
Gérer la mémoire avec des listes chaînées
Best Fit

• Algorithme du meilleur ajustement


– Parcourt toute la liste et recherche le plus
petit trou pouvant contenir le processus.
– Évite de partitionner inutilement les gros trous
– Cet algorithme crée des trous minuscules
inutilisables par la suite
– Plus lent que les algorithmes précédents

12/15/16 36
Gérer la mémoire avec des listes chaînées
Worst Fit

• Algorithme du plus grand résidu


– On prend le plus grand trou disponible
– Le trou restant est assez grand pour être
réutilisé
– Des simulations démontrent que cette
solution n’est pas meilleure que la
précédente.

12/15/16 37
Gérer la mémoire avec des listes
chaînées
• On peut utiliser deux listes distinctes (zones libres et
occupées par un processus)

• Accélère les algorithmes précédents


– Si la liste des trous est triée par taille alors best-fit et first-fit sont
essentiellement équivalents.

• Ralentissement quand la mémoire est libérée


– Un segment libéré est enlevé de la liste des processus et inséré dans la
liste des trous

• On peut utiliser les zones libres elle même pour la liste des
zones libres

12/15/16 38
Gérer la mémoire avec des listes chaînées
Quick Fit
• Algorithme du placement rapide (quick fit)
– On gère des listes séparées pour certaines des tailles les
plus communes
– Par exemple, on peut avoir des listes de 4Ko, 8Ko, 12Ko, etc.
– Très rapide.
– Rend plus complexe le processus de libération de la
mémoire: On doit chercher les trous adjacents pour une
vérifier si une fusion est possible.

• Tous ces algorithmes souffrent du problème de la


fragmentation de la mémoire.

12/15/16 39
Application #1

12/15/16 40
Application #1
● Considérons un système de gestion de mémoire à
partitions variables avec la liste des trous suivante
(ordonnée par adresses croissantes) : 10K, 4K, 20K,
18K, 7K, 9K, 12K et 15K.

● Supposons les demandes successives d'espace


mémoire :A= 12K, B= 10K et C= 9K.

● Indiquer pour les stratégies First Fit, Next Fit, Best


Fit et Worst Fit l'état de cette liste après l'allocation
des espaces pour les demandes de A, B et C.

12/15/16 41
Solution Application #1
● First fit : on cherche le premier espace
qui convient
@ Lg @ Lg @ Lg @ Lg
a 10k a 10k b 4k b 4k
b 4k b 4k c 8k c 8k
c 20k c 8k d 9k
d 18k
d 18k d 18k
e 7k e 7k
e 7k e 7k
f 9k f 9k
f 9k f 9k
g 12k g 12k
g 12k g 12k
h 15k C h 15k
h 15k h 15k
9k
A B
12/15/16 42
12k 10k
Solution Application #1
● Next Fit : on cherche l’espace suivant
qui convient
@ Lg @ Lg @ Lg @ Lg
a 10k a 10k a 10k a 10k
b 4k b 4k b 4k b 4k
c 20k c 20k c 10k c 1k
d 18k d 6k d 6k d 6k
e 7k e 7k e 7k e 7k
f 9k f 9k f 9k f 9k
g 12k g 12k g 12k g 12k
h 15k h 15k h 15k h 15k
C
A B
12/15/16 9k 43
12k 10k
Solution Application #1
● Best fit : on cherche l’espace qui laisse
le plus petit trou
@ Lg @ Lg @ Lg @ Lg
a 10k a 10k b 4k b 4k
b 4k b 4k c 20k c 20k
c 20k c 20k d 18k d 18k
d 18k d 18k e 7k e 7k
e 7k e 7k f 9k h 15k
f 9k f 9k h 15k
g 12k h 15k C
h 15k 9k
B
A 10k
12/15/16 44
12k
Solution Application #1
● Worst fit : on cherche l’espace qui
laisse le plus grand vide
@ Lg @ Lg @ Lg @ Lg
a 10k a 10k a 10k a 10k
b 4k b 4k b 4k b 4k
c 20k c 8k c 8k c 8k
d 18k d 18k d 8k d 8k
e 7k e 7k e 7k e 7k
f 9k f 9k f 9k f 9k
g 12k g 12k g 12k g 12k
h 15k h 15k h 15k h 6k
A B C
12/15/16 45
12k 10k 9k
LA MÉMOIRE VIRTUELLE

12/15/16 46
La mémoire virtuelle
• Si la taille des mémoires augmente, celle des
logiciels augmente encore plus vite
– Dans les années 1980, on faisait tourner en temps partagé
des dizaine d’utilisateurs sur des VAX dotés de 4Mo.
– Vista/Seven (mono-utilisateur) recommande au minimum 1
Go

• On est sûr d’être à court de mémoire


– Le swapping n’est pas une bonne option en raison des
volumes à transférer: il faut au moins 10s pour mettre un
programme de 1 Go sur un disque SATA au débit crête de
100Mo/s

12/15/16 47
La mémoire virtuelle
• Le problème de programme plus gros que la mémoire
est connu depuis longtemps

• Dans les années 1960, la solution la plus courante


consistait à diviser le programme en parties, appelées
segments de recouvrement (overlay)
– Le segment 0 était exécuté en premier
– Quand cela était réalisé, il pouvait appeler un autre
segment
– Le va-et-vient est géré par le système, la division en
overlay est géré par le programmeur!
– Solution rapidement abandonnée

12/15/16 48
La mémoire virtuelle

• La méthode qui a été imaginée est connue aujourd’hui sous le


nom de mémoire virtuelle.

• La mémoire virtuelle repose sur le principe suivant: chaque


programme a son propre espace d’adressage découpé en petites
entités appelées pages, entités formées d’une suite d’adresse
contiguës
– La taille des page est fixe (typiquement entre 512 octets à 64Ko)

• Les pages sont mappées sur la mémoire physique, mais il n’est


pas obligatoire d’avoir toutes les page en mémoire physique pour
exécuter le programme.

12/15/16 49
La pagination
• Les adresses générées par programme sont
appelées des adresses virtuelles et elle
forment l’espace d’adressage virtuel

• Dans les ordinateurs sans mémoire virtuelle,


l’adresse est placée directement sur le bus
mémoire et provoque la lecture ou l’écriture
du mot de même adresse physique

• Dans les ordinateurs avec mémoire virtuelle,


l’adresse est placée dans une unité de
gestion mémoire (MMU Memory Mangement
Unit) qui fait correspondre les adresses
virtuelles à des adresses physiques

• La relation entre les adresses virtuelles et


physiques est indiquée dans la table des
pages

12/15/16 50
La pagination
• Un ordinateur peut produire de adresses
sur 16 bits avec des valeurs comprises
entre 0 et 64Ko: ce sont les adresses
virtuelles.

• Toutefois, cet ordinateur a seulement


32Ko de mémoire physique;
– par conséquent, même s’il permet d’ écrire
des programmes de 64Ko, ceux-ci ne
peuvent pas être chargés entièrement dans
la mémoire et exécutés.
– Il faut cependant qu’une copie complète de
tout le programme soit présente sur le
disque, afin que les différentes parties
puissent être récupérer quand cela est
nécessaire

12/15/16 51
La pagination
• L’espace d’adressage virtuel est
divisé en unités appelées pages

• Les unités correspondantes dans


la mémoire physique sont
appelées cadres de pages (pages
frames)
– Les pages et les cadres de pages
ont toujours la même taille (4Ko
dans notre exemple)
– Chaque page est indivisible: Elle est
entièrement en mémoire physique
ou elle n’y est pas du tout.

12/15/16 52
La pagination
• L’indication 0K-4K signifie que
les adresse virtuelles ou réelles
de la page sont situées entre 0
et 4095

• L’indication 4K-8K entre 4096-


8191

• Chaque page contient 4096


adresses qui démarrent à un
multiple de 4096 et finissent au
multiple suivant

12/15/16 53
La pagination
L’adresse virtuelle 0 est
transformée en adresse
physique 8192=2*4096

L’adresse virtuelle 8192=2*4096


est transformée en adresse
physique 24576=6*4096

L’adresse virtuelle
20500=5*4096+20 est
transformée en adresse
physique 12308=3*4096+20

12/15/16 54
La pagination
• Quand le programme essaie par exemple
d’accéder à l’adresse 0, à l’aide de
l’instruction
– MOV REG,0

• L’adresse virtuelle 0 est envoyée à la


MMU. La MMU constate que cette adresse
virtuelle tombe dans la page 0 ( de valeurs
comprises entre 0 et 4095), laquelle
correspond au cadre de la page 2 ( de
valeurs comprises entre 8192 et 12287)
– Elle transforme l’adresse en 8192 et la
présente sur le bus

• La mémoire ne sait rien de la MMU: elle


interprète seulement qu’il s’agit d’une
requête de lecture ou d’écriture à
l’adresse 8192, et elle le réalise.
12/15/16 55
La pagination
• Cette capacité de mettre en
correspondance les 16 pages virtuelles
sur les 8 cadres de pages ne résout pas
le problème posé par un espace
d’adressage virtuel plus grand que la
mémoire physique

• Seule 8 des pages virtuelles sont mise


en correspondance avec la mémoire
physique

• Un bit de présence/absence conserve la


trace des pages qui se trouvent
physiquement en mémoire

• Que se passe-t-il si le programme


essaye de faire appel à une page non
présente avec l’instruction MOV
REG,32780 ????
12/15/16 56
La pagination
• MOV REG,32780 correspond à l’octet 12 de
la page virtuelle 8 (qui commence à 32768)

• La MMU remarque que la page est absente


(ce qui est indiqué par une croix dans la
figure) et fait procéder l’UC à un
déroutement, c’est-à-dire que le processeur
est restitué au système d’exploitation

• Ce déroutement, appelé défaut de page


(page fault), est réalisé de la manière
suivante:
– Le système d’exploitation sélectionne un cadre
de page peu utilisé
– et écrit son contenu sur le disque;
– il transfère ensuite la page qui vient d’être
référencée dans le cadre de page libéré,
– modifie la correspondance et recommence
l’instruction déroutée.
12/15/16 57
La pagination
• Par exemple, si le système d’exploitation
décide de déplacer le cadre de la page 1
– Il doit charger la page virtuelle 8 à l’adresse
physique 4K et faire deux correspondance dans la
MMU.

• Tout d’abord, il doit marquer l’entrée de la


page virtuelle 1 comme étant non utilisée,
afin d’autorisé tout accès ultérieur aux
adresses virtuelles comprise entre 4K et 8K

• Ensuite il devra remplacer la croix de l’entrée


de la page 8 par la valeur 1

• Enfin, quand l’instruction déroutée sera ré-


exécutée, il mettra l’adresse virtuelle 32780
en correspondance avec l’adresse physique
4108 (4096 +12)

12/15/16 58
La pagination: fonctionnement interne d’une MMU

• Adresse virtuelle 8196, en


binaire 0010000000000100
est divisée en deux
parties
– Un numéro de page sur 4
bits et un décalage sur 12
bits
– Avec 4 bits pour le numéro
de page nous pouvons
avoir 16 pages
– Avec 12 bits pour le
décalage, nous pouvons
adresser l’ensemble des
4096 octets d’une page

12/15/16 59
La pagination: fonctionnement interne d’une MMU

• Le numéro de page est


utilisé comme un index
dans la table des pages:
– Le numéro du cadre de
page correspond à la page
virtuelle

• Si le bit de
présence/absence est à
0, un déroutement vers le
système d’exploitation
est mis en place

12/15/16 60
La pagination: fonctionnement interne d’une MMU

• Si le bit est à 1,
– le numéro de cadre de page trouvé
dans la table des page et copié
dans les 3 bits de poids le plus fort
du registre de sortie
– auxquels sont ajoutés les 12 bits de
décalage, qui sont copié à partir de
l’adresse virtuelle entrante sans
être modifiée
– ils forment ensemble une adresse
physique sur 15 bits

• Le registre de sortie est ensuite


placé sur le bus mémoire en tant
qu’adresse de mémoire physique

12/15/16 61
Les tables de pages
• Le rôle d’une table des pages est ainsi de faire
correspondre des pages virtuelles à des cadres de page
– C’est une fonction qui a comme argument le numéro de la
page virtuelle et comme résultat le cadre physique
– Le résultat de cette fonction peut servir à remplacer le champ
nommé page virtuelle d’une adresse virtuelle par un champ
nommée cadre de page et à créer ainsi une adresse mémoire
physique

• Deux problèmes:
– La table des pages peut être très grande
– Trouver l'adresse réelle à partir de l'adresse virtuelle doit se
faire très rapidement

12/15/16 62
Récapitulons :
• Dans le cas le plus simple, la mise en correspondance des adresses virtuelles et
des adresses physiques se déroule comme suit
– L’adresse virtuelle est séparée en deux parties
– Un numéro de page virtuelle (les bits de poids fort)
– Et un décalage (les bits de poids faible)

• Avec une adresse de 16 bits et une taille de page de 4 Ko,


– les 4 bits de poids fort peuvent spécifier une des 16 pages virtuelles,
– les 12 bits de poids faible indiqueront alors le décalage en octet ( de 0 à 4095)

• Dans la table des pages, le numéro de page virtuelle sert à trouver l’entrée de la
page virtuelle.
– S’il existe, le numéro du cadre de page est trouvé à partir de cette entrée de la table des pages

• Le numéro du cadre de page est attribué aux bits de poids fort suivi du décalage,
remplaçant le numéro de page virtuelle, pour composer une adresse physique qui
peut être envoyée à la mémoire

12/15/16 63
Structure d’un entrée de table de page

• Le champ le plus important est le numéro de cadre de page


– L’objectif est de localiser cette valeur

• Présent/Absent:
– si 0 cela provoque un défaut de page
– Si 1, l’entrée est valide et peut être utilisé

• Protection: précise quelles sortes d’accès sont permis


– lecture, écriture, exécution

12/15/16 64
Structure d’un entrée de table de page

• Modifié (dirty/clean bit) :


– Si aucune modification (clean), il n’est pas nécessaire de sauvegarder sur le disque. Lors d’une
écriture (dirty), automatiquement mis à 1

• Référencé:
– Mis à 1 chaque fois qu’une page est consultée
– Permet de décider si la page peut être remplacer par une autre
– Les pages qui ne sont pas en cours d’utilisation sont de meilleures candidates que les autres

• Cache inhibée:
– Caractéristique importante pour les pages qui sont mises en correspondance dans des registres
matériel plutôt qu’en mémoire
– Utile pour les attentes de réponse d’E/S on veut accéder aux données du périphérique plutôt qu’au
cache

12/15/16 65
Application #2

12/15/16 66
Exercice 1 : Pagination Simple

Sur un système de pagination simple de 2¹⁶ octets de


mémoire physique de 2¹² pages d'espace d'adressage
virtuel et une taille de page de 4 ko (=4096 octets).
1) Combien de bits se trouvent dans une adresse virtuelle ?
2) Combien d'octets se trouvent dans un cadre de page ?
3) Combien de bits de l'adresse physique spécifient le cadre de page ?
4) Combien d'entrées se trouvent dans la table de pages ?
5) Combien de bits sont nécessaires pour stocker une entrée dans la table de
pages (de quelle largeur est la table de pages) ?

● Hypothèse :
– Chaque entrée de table de pages contient, en plus du numéro de cadre de page, 1
bit de présence (P), 1 bit pour son référencement (R) et 1 bit pour sa modification
(M).

12/15/16 67
Solution Exercice 1 : Pagination Simple

● 1- Combien de bits se trouvent dans une


adresse virtuelle ?
– L’espace d’adressage logique contient 2¹² = 4096 pages de 4
ko = 2¹² octets chacune, soit un espace d’adressage total de
2¹² x 2¹² = 2²⁴ octets. Pour couvrir cet espace d’adressage,
l’adresse virtuelle sera codée sur 24 bits : 12 bits pour les
pages et 12 bits pour le déplacement dans la page

● 2- Combien d'octets se trouvent dans un cadre


de page ?
– 4096 octets

12/15/16 68
Solution Exercice 1 : Pagination Simple


3- Combien de bits de l'adresse physique spécifient le cadre de
page ?
– L’espace d’adressage physique est de 2¹⁶ octets. Étant donné que les pages font 2¹²
octets, on peut donc écrire 2¹⁶= 2¹² * 2⁴ . Ceci implique une adresse physique de 16
bits définie avec 4 bits pour les numéros des cadres et 12 bits pour le déplacement
dans une page.


4- Combien d'entrées se trouvent dans la table de pages ?
– La table des pages doit contenir une entrée pour chaque page. Comme il y a 2¹²
pages, la taille de la table des pages doit donc avoir une longueur de 2¹² = 4096
entrées.


5- Combien de bits sont nécessaires pour stocker une entrée
dans la table de pages (de quelle largeur est la table de pages) ?
– Chaque entrée contient 3 bits pour indiquer P, R et M et 4 bits pour spécifier le
numéro du cadre de page ; ce qui donne au total 3 + 4 = 7 bits par entrée.

12/15/16 69
Accélérer la pagination
• Tout système de pagination doit considérer deux éléments
1. La correspondance doit être rapide
2. La table des pages doit être très grande

• Accélérer la correspondance
–.La correspondance entre mémoire virtuelle et mémoire physique doit être
réalisée à chaque référence mémoire
–.Un instruction typique: un mot d’instruction + opérande mémoire
–.Chaque instruction : on fait référence à la table des pages au moins
une fois

•. La table des pages doit être très grande


–.Les adresses virtuelles courante d’au moins 32bits (souvent 64 bits)
–.Une page de 4Ko, un espace d’adressage de 32 bits a 1 Million de pages
–.Avec un 1 Million de page dans l’espace d’adressage virtuel, la table
des pages doit avoir 1 Million d’entrées

12/15/16 70
La mémoire associative
• Hypothèse: la table des pages est en mémoire
– Impact considérable sur les performances
– Par exemple une instruction qui copie un registre dans un autre

En l’absence de pagination: cette instruction fait une seule
référence mémoire

Avec la pagination: des références mémoires supplémentaires
peuvent être nécessaire pour accéder à la table des pages

• Observation:
– La plupart des programmes tendent à faire un grand nombre de
référence à un petit nombre de pages
→ Seule un petite fraction des entrées de la table des pages est
réellement lue, tout le reste sert rarement

12/15/16 71
La mémoire associative
• Solution
– équiper les ordinateurs avec un périphérique qui permet de mettre en
correspondance les adresses virtuelles avec les adresses physique sans passer
par la table des pages
– TLB: Translation Lookaside Buffer
– Appelé aussi mémoire associative, se trouve à l’intérieur de la MMU

• Le TLB consiste en un petit nombre d’entrées qui sont rarement


plus de 64
– Chaque entrée contient les informations d’une page:
• le numéro de la page virtuelle,
• un bit mis à 1 quand la page est modifiée,
• le code de protection (RWX)
• la cadre de page physique dans lequel la page est utilisé
• Un bit indique si l’entrée est valide (càd utilisée) ou non

– Ces champs étalissent une correspondance point à point avec les champs de la
page

12/15/16 72
La mémoire associative
Valide Page virtuelle Modifié Protection Cadre de page
indices
code
données
données
code
code
pile
pile

• Un processus (boucle + tableau)


– Les données principales sont dans les pages 129,130
– Page 140 indice de parcours
– Pile 860, 861
– Code 19,20,21
12/15/16 73
La mémoire associative

• Quand une adresse virtuelle est présentée à la


MMU pour être traduite
– Le matériel vérifie si ce numéro de page virtuelle est
présent dans le TLB
– Si une correspondance est trouvée et si l’accès n’enfreint
pas la pas les bits de protection, le cadre de page est
pris directement dans le TLB sans passer par la table
des pages
– Si le numéro de page virtuelle est présent dans le TLB
mais l’instruction essaie d’écrire dans un cadre autorisée
en lecture seule, une erreur de protection est générée

12/15/16 74
La mémoire associative

• Lorsque le numéro de page virtuelle


n’est pas dans le TLB
– La MMU détecte l’erreur et parcourt
normalement la table des pages
– Elle efface une des entrées du TLB et la
remplace par l’entrée de la table des pages
trouvée
– Si cette page est réutilisée rapidement, il en
résultera cette fois un accès plutôt qu’une
erreur
12/15/16 75
Les tables des pages des grandes
mémoires
• On utilise les TLB pour accélérer la
traduction d’adresse virtuelles en
adresses physiques, mais ce n’est pas
le seul problème à traiter

• Il faut aussi gérer de très grandes


mémoires. Deux solutions:
1. Tables des pages multi-niveaux
2. Tables des pages inversées
12/15/16 76
Tables des pages multi-niveaux
• Une adresse de 32 bits est
subdivisé en
– Un champ de 10 bits nommé
PT1
– Un champ de 10 bits nommé
PT2
– Un champ de 12 bits nommé
Décalage

• Puisque les décalages


sont sur 12 bits, les pages
font 4 Ko (4*1024) et nous
avons au total 220 pages.

12/15/16 77
Tables des pages multi-niveaux
• Avec la méthode des tables
de pages multi-niveau, on ne
garde pas en mémoire toutes
les tables de pages en
particulier celles dont nous
n’avons pas besoin.

• Exemple: Un processus a
besoin de 12 Mo: 4Mo
inférieur pour le code, 4 Mo
pour les données, 4 Mo pour
la pile

12/15/16 78
Tables des pages multi-niveaux
• Le 1er niveau correspond au champ
PT1 (1024 entrées)

• Lorsqu’une adresse virtuelle est


présentée à la MMU, elle extrait le
champ PT1 et emploi cette valeur
comme index dans le table du
premier niveau

• Chacune de ces 1024 entrées


représente 4Mo, parce que la
totalité des 4 Go (32bits) de
l’espace d’adressage a été découpé
en morceaux de 4096 octets.

12/15/16 79
Tables des pages multi-niveaux
• L’entrée localisée par
l’indexation de la table des
pages de niveau 1 produit
l’adresse ou le numéro de
cadre de page de la table des
pages de second niveau

• Le champ PT2 est maintenant


employé comme index dans la
table des pages de second
niveau sélectionnée pour
trouver le numéro du cadre de
page de la page elle-mêmes

12/15/16 80
Tables des pages multi-niveaux

• À titre d’exemple
– Considérons
l’adresse virtuelle sur
32bits 0x00403004
soit:
– 0000 0000 01 | 00
0000 0011 | 0000 0000
0100
– PT1 = 1, PT2 =3,
Décalage = 4
12/15/16 81
Tables des pages inversés
• Pour les processeurs 64 bits, l’espace d’adressage est
de 264 bits, avec des pages de 4 Ko, il faut une table des
pages avec 252 entrées
– 264 /4*1024 = 264 /22*210 = 264/212 = 252
– Si chaque entrée est sur 8 bits, la taille de table sera
supérieur à 30 Millions de Go !!!!

• Solution: tables des pages inversée


– Une table de pages unique pour tout le système, indexée par les
cadres de page
– Chaque entrée contient un numéro de processus et un numéro
de page virtuelle

12/15/16 82
Table de pages inversée

• On trouve une entrée par cadre de page dans


la mémoire réelle, plutôt qu’une entrée par
page de l’espace d’adressage virtuel

• Problèmes
– Liaison d’adresse plus compliquée (parcours de la
table)

• Utilisation actuelle : IBM, HP, de plus en plus


d’architectures 64 bits
12/15/16 83
Application #3

12/15/16 84
Exercice  : tables de pages multi-niveaux

● On considère un système de pagination à deux niveaux. Les


adresses (virtuelles et physiques) sont codées sur 32 bits.
● Les 10 premiers bits d’une adresse virtuelle forment le premier index de pagination
(table des premier niveau)
● Les 10 suivants forment le second niveau (celui des tables d’index relatives à
chaque entrée de la table de premier niveau)
● Les 12 bits restant forment le déplacement.
● Chacune des entrées de ces tables de pagination occupe 32 bits.

1)Quelle est la taille d’une page ?


2)Quelle est l’espace nécessaire pour stocker la table de premier
niveau ?
3)Faites un petit dessin illustrant, dans ce contexte, la traduction
d’une adresse virtuelle en une adresse physique

12/15/16 85
Correction Exercice  : tables de pages multi-
niveaux
1) Le déplacement dans une page est sur 12 bits. Donc sa
taille est de 4 kilos
2) La table de premier niveau contient 1024 entrées (10 bits
du premier niveau d’index de pagination). Chaque entrée
occupe 32 bits. Donc la table des hyper-pages occupe 32
kilo

12/15/16 86
Correction Exercice 1 : tables de pages multi-
niveaux

12/15/16 87
LES ALGORITHMES DE
REMPLACEMENT DE PAGES

12/15/16 88
Les algorithmes de remplacement de
pages
• Quand un défaut de page se produit, le S.E doit
choisir une page à enlever de la mémoire afin de
faire de la place pour la page qui doit être chargée

• Si la page qui doit être supprimée a été modifie


quand elle était en mémoire, elle doit être réécrite sur
le disque pour mettre à jour la copie disque

• Si la page n’a pas changé, la copie disque est déjà à


jour et ne nécessite pas de réécriture. La page à lire
écrasera simplement la page devant être évincée.

12/15/16 89
Les algorithmes de remplacement de
pages
• Bien qu’il soit possible de choisir au hasard la page à
supprimer à chaque défaut de page, les performances du
système seront meilleures si c’est une page peu utilisée qui
est choisie

• Si une page souvent employée est enlevée, il faudra


probablement qu’elle soit rechargée rapidement, ce qui
entraînera un dépassement supplémentaire.

• La question fondamentale: doit-on supprimer de la mémoire


une page appartenant au processus qui en demande une
nouvelle, ou peut-on éliminer une page d’un autre processus
?

12/15/16 90
L’algorithme optimal de remplacement
de page
• Le meilleur algorithme de remplacement de page
imaginable est facile à décrire mais impossible à implanter.

• Au moment où un défaut de page est générer, plusieurs


pages sont en mémoire. Une de ces pages sera référencée
par une très prochaine instruction. Il se peut d’autres pages
ne soient pas référencées avant la dixième, la centième ou
la millième instruction qui suit

• Chaque page peut être étiquetée avec le nombre


d’instruction qui seront exécutés avant que cette page ne
soit référencée.

12/15/16 91
L’algorithme optimal de remplacement
de page
• L’algorithme de page optimal dit simplement que c’est la
page dont l’étiquette est la plus grande qui sera enlevée.
– Si une page n’est pas utilisée avant 8 millions d’instructions et une
autre page avant 6 millions d’instructions,
– la suppression de la première repousse le défaut de page aussi
tard que possible

• Le seul problème avec cet algorithme est qu’il est


irréalisable
– Au moment où survient le défaut de page, le S.E n’a aucun moyen
de savoir quand chacune de ces pages sera référencée à la
prochaine fois

12/15/16 92
L’algorithme de remplacement de la
page non récemment utilisée
• Afin de permettre au système d’exploitation de
collecter des statistiques utiles sur le nombre de
pages utilisées et le nombre de page inutilisées, la
plupart des ordinateurs avec mémoire virtuelle
possèdent 2 bits d’état associés à chaque page.
– Le bit R est mis à 1 à chaque fois que la page est
référencée (lue ou écrite) et le bit M est mis à 1 quand la
page est réécrite (modifiée par rapport à la version du
sauvegardé sur le disque)
– Ces bits doivent être mis à jour à chaque référence
mémoire, et qu’il est donc essentiel que cette mise à jour
soit matérielle

12/15/16 93
L’algorithme de remplacement de la
page non récemment utilisée
• Quand un processus démarre, les 2 bits de page pour toutes ses
pages sont mis à 0 par le S.E

• Périodiquement (chaque interruption d’horloge) , le bit R est


effacé, afin de distinguer les pages qui n’ont pas été récemment
référencées de celles qui l’ont été.

• Quand un défaut de page est généré, le S.E examine touts les


pages et les sépare en quatre catégories basées sur les valeurs
courantes de R et M
– Classe 0 : non référencée, non modifiée
– Classe 1 : non référencée, modifiée
– Classe 2 : référencée, non modifiée
– Classe 3 : référencée, modifiée

12/15/16 94
L’algorithme de remplacement de la
page non récemment utilisée
• Bien que l’existence de page de classe 1 semble impossible
à première vue, celles-ci sont générées lorsque le bit R d’une
page de classe 3 est effacé par une interruption d’horloge
– Les interruptions d’horloge n’effacent pas le bit M parce que cette
information est nécessaire pour savoir si la page a été réécrite sur le
disque ou pas
– Si le bit R est effacé mais pas le bit M, cela aboutit à la classe 1.

• L’algorithme de la page non récemment utilisé ou NRU (Not


Recently Used) enlève une page au hasard dans la classe la
plus basse non vide.
– Il vaut mieux enlever une page modifiée qui n’ pas été référencée plutôt
qu’une page qui est beaucoup utilisée.

12/15/16 95
L’algorithme de remplacement de
page premier entrée, premier sorti
• Le S.E maintient une liste FIFO de toutes les pages
couramment en mémoire, la page la plus ancienne
étant en tête de liste et la page la plus récente en
queue

• Dans le cas d’un défaut de page, la page en tête de la


liste est effacée et la nouvelle page ajoutée en queue
de liste

• Inconvénient
– les vieilles pages peuvent aussi être celles qui sont le plus
utilisées

12/15/16 96
L’algorithme de remplacement de
page de la seconde chance
• On peut apporter une modification simple à
l’algorithme FIFO afin d’éviter la suppression d’une
page à laquelle on a couramment recours.

• Il s’agit d’inspecter le bit R de la page la plus


ancienne
– S’il est à 0, la page est à la fois ancienne et inutilisée, elle est
donc remplacée immédiatement
– Si le bit R est à 1, le bit est effacé, la page est placée à la fin
de la liste des pages, et son temps de chargement est mis à
jour comme si elle venait d’arriver en mémoire
– La recherche continue alors

12/15/16 97
L’algorithme de remplacement de
page de la seconde chance

• Opération seconde chance:


– pages triées selon l'ordre d'arrivé
– Si le bit R de la page la plus ancienne est 1 alors on la met à
la fin de la liste (comme une nouvelle page) et on met son bit
R à 0.

12/15/16 98
L’algorithme de remplacement de
page de la seconde chance
• Supposons qu’un défaut de page
se produise à l’instant 20, la page
la plus ancienne est A, qui arrivée à
l’instant 0, au démarrage du
processus

• Si le bit R est à 0, A est évincée de


la mémoire: elle est soit écrite sur
le disque (si elle est modifié), soit
simplement abandonnée

• Si le bit R est à 1, A est placé à la


fin de la liste et son temps de
chargement est mis à jour avec le
temps courant (20). Le bit R est mis
à 0.

12/15/16 99
L’algorithme de remplacement de
page de la seconde chance
• Le travail de l’algorithme de la seconde chance
consiste à chercher une ancienne page qui n’a pas
été référencée dans le précédent intervalle
d’horloge.

• Si toutes les pages on été référencées, l’algorithme


de la seconde chance dégénère en pur FIFO

12/15/16 100
L’algorithme de remplacement de
page de la seconde chance
• Si toutes les pages ont été
référencés (R=1), le S.E
deplace une par une les pages
à la fin de la liste,
– effaçant le bit R chaque fois qu’il
ajoute une page à la fin de la
liste.

• Finalement il revient à la page


A, dont le bit R est à 0. A ce
moment, A est évincée

• L’algorithme se termine
toujours

12/15/16 101
Algorithme de l'horloge
• Bien que l’algorithme de la seconde
chance soit un algorithme
satisfaisant, il manque d’efficacité
parce qu’il déplace constamment
des pages dans sa liste

• Une meilleure approche consiste à


garder tous les cadres de pages
dans une liste circulaire formant
une horloge. Un pointeur se trouve
sur la page la plus ancienne.

• Comme l'algorithme précédent mais


l'utilisation d'une liste circulaire
évite de déplacer les pages

12/15/16 102
Algorithme de l'horloge
• Quand un défaut de page
survient, la page pointée est
examinée.
– Si son bit R est à 0, la page est
évincée, la nouvelle page est
insérée dans l'horloge à sa place, et
le pointeur est avancé d'une
position.
– Si le bit R est à 1, il est effacé et le
pointeur est avancé sur la
prochaine page.
– Ce processus est répété jusqu'à ce
qu'une page R = 0 soit trouvée.
– Cet algorithme de l'horloge diffère
de l'algorithme de la seconde
chance uniquement dans son
implémentation

12/15/16 103
L'algorithme de remplacement de la
page la moins récemment utilisée
• Pour s'approcher au mieux de l'algorithme optimal, il faut se
fonder sur l'observation suivante : les pages les plus
référencées lors des dernières instructions seront
probablement très utilisées dans les prochaines
instructions.

• À l'inverse, des pages qui n'ont pas été employées depuis


longtemps ne seront pas demandées avant un long moment.

• On peut en déduire l'algorithme suivant: quand un défaut de


page se produit, c'est la page qui n'a pas été utilisée pendant
le plus de temps qui est retirée.

12/15/16 104
L'algorithme de remplacement de la
page la moins récemment utilisée
• Cette méthode est appelée pagination LRU (Least Recently
Used, la moins récemment utilisée).

• Cet algorithme LRU est réalisable mais reste coûteux.


– Mettre à jour cette liste à chaque référence mémoire: Couteux!!
– Pour l’implémenter totalement, il est nécessaire de gérer une liste
chaînée de toutes les pages en mémoire, avec la page la plus
récemment utilisée en tête et la moins utilisée en queue.
– La difficulté est que cette liste doit être mise à jour à chaque référence
mémoire.
– La recherche d'une page dans la liste, sa destruction et son
déplacement en début de liste sont des opérations coûteuses en temps,
même si elles sont réalisées de manière matérielle (en supposant qu'un
tel matériel existe)

12/15/16 105
L'algorithme de remplacement de la
page la moins récemment utilisée
• Cependant, il existe d'autres manières d’implémenter cet algorithme avec
des composants matériels particuliers.

• Considérons la plus simple d'entre elle. Cette méthode nécessite d'équiper


le matériel avec un compteur 64 bits, « c », qui s'incrémente
automatiquement après chaque instruction.
– Par ailleurs, chaque entrée de la table des pages doit avoir un champ assez grand
pour contenir ce compteur.

• Après chaque référence mémoire, la valeur courante de « c » est enregistrée


dans l'entrée de la table des pages pour l'entrée qui vient d'être référencée.

• Quand un défaut de page se produit, le S.E examine tous les compteurs


dans la table des pages afin de trouver le plus petit d'entre eux. Celui-ci
correspond à la page la moins récemment utilisée.

12/15/16 106
L'algorithme de remplacement de la
page la moins récemment utilisée
• Examinons à présent une deuxième solution matérielle.
Pour une machine à n cadres de pages, le matériel doit
gérer une matrice de n * n bits, initialement tous nuls.

• Quand une page k est référencée, le matériel


commence par mettre à 1 tous les bits de la rangée k et
tous les bits de la colonne k à 0.

• À chaque instant, la rangée dont la valeur binaire est la


plus petite indique la page la moins récemment utilisée

12/15/16 107
L'algorithme de remplacement de la
page la moins récemment utilisée
Référence des pages: 0,1,2,3,2,1,0,3,2,3

12/15/16 108
La simulation logicielle de l’algorithme
LRU
• Bien que le deux algorithmes LRU
précédents soient réalisables, peu de
machines disposent du matériel
adéquat.

• À la place, une solution logicielle peut


être implantée
– NFU: Not Frequently Used
– L’algorithme de vieillissement
12/15/16 109
L’algorithme NFU

• Il nécessite un compteur logiciel par page,


initialement à 0

• À chaque interruption d’horloge, le S.E examine


toutes les pages en mémoire
– Pour chaque page, le bit R de valeur 0 ou 1, est ajouté à
son compteur
– Le compteur mémorise les différents référencements de
page
– Quand un défait de page se produit, c’est la page avec le
plus petit compteur qui est remplacée

12/15/16 110
L’algorithme NFU

• Le problème principal de NFU est qu’il n’oublie


rien.
– Dans un compilateur à plusieurs passes, les compteurs
des pages très utilisées au cours de la première passe
ont des valeurs élevées lors des passes suivantes
– Si la première passe a le plus long temps d’exécution,
les pages contenant le code des passes suivantes ont
toujours un compteur plus faible que les pages de la
première passe
– Les système d’exploitation aura donc tendance à retirer
des pages utiles plutôt que des pages non utilisées.

12/15/16 111
Algorithme de vieillissement
• Il existe néanmoins une petite modification que l’on peut
apporter à l’algorithme NFU pour lui permettre de se
comporter comme l’algorithme LRU

• Cette modification se réalise en deux temps:


– Les compteurs sont décalés d’un bit à droite avant d’être ajoutés au bit R
– Ensuite, le bit R est ajouté au bit de poids le plus fort (le bit de gauche)
plutôt que le bit le plus faible

• Supposons qu’après le premier top d’horloge, les bits R des


pages 0 à 5 aient les valeurs 1,0,1,0,1,1
– Entre les tops d’horloge 0 et 1, les pages 0,2,4,5 sont référencés et leurs
bits R sont mis à 1, alors que les autres restent à 0.

12/15/16 112
Algorithme de vieillissement

• Un compteur logiciel par page (initialisé à 0)


• À chaque interruption d'horloge, on examine toutes les
entrées de la table des pages
• On décale à droite le compteur et on ajoute à gauche le bit R

12/15/16 113
Algorithme de vieillissement

• Quand un défaut de page se produit, la page


dont compteur est le plus petit est retirée

• Il est évident qu’une page qui n’a pas été


référencée pendant 4 tops d’horloge a
quatre 0 dans son compteur
– De ce fait elle aura une petite valeur que le
compteur de page non référencée pendant 3 tops
d’horloge

12/15/16 114
LA SEGMENTATION

12/15/16 115
Problèmes de la pagination

• Sécurité des zones mémoire


– Comment le système peut-il s’assurer qu’un
processus utilise à bon escient son espace
mémoire alloué ?

– Comment peut-il s’assurer que certaines


zones mémoires restent correctement
protégées en lectures, écritures et/ou
exécution ?

12/15/16 116
Problèmes de la pagination

• Gestion dynamique de la mémoire


– Certains programmes gèrent de grandes
quantités de mémoire dont on ne peut prédire
l’évolution
– Prévoir une trop grande quantité de mémoire
peut être pénalisant pour les performances
générales du système
– En prévoir une trop petite peut limiter
l’utilisation du programme

12/15/16 117
Problèmes de la pagination
• Bibliothèque chargées dynamiquement lors de
l’exécution du code
– Les S.E s’appuient sur des bibliothèques dynamiques pour
rendre les logiciels moins dépendant des différents versions des
services fournis par le système
– Ces bibliothèques ont une interface d’appel bien définie mais ne
sont pas incluses dans le logiciel qui les utilise
– C’est seulement au moment où elles sont nécessaire que le
système les charge en mémoire et les exécute
– → Ces bibliothèque ne savent pas à l’avance à quel offset
elles se trouveront dans l’espace du processus, ce qui
complique considérablement l’édition de liens à la volée que
nécessite leurs chargement

12/15/16 118
Principes de la segmentation
• Comment libérer le programmeur de la gestion de
l’accroissement et de la diminution des tables?

• Un solution consiste à doter la machine de plusieurs


espaces d’adresses indépendants appelés segments.
– Chaque segment est une suite d’adresse continues de 0 à une
adresse maximale
– La longueur de chaque segment peut être comprise en 0 et la
longueur maximale autorisée
– Les segments ont en générale des longueurs différentes
– De plus leurs longueur peut varier en cours d’exécution
– La longueur du segment de pile peut par exemple être augmentée
lorsque quelque chose est empilé et diminuée lors d’un dépilement

12/15/16 119
Principes de la segmentation
• la segmentation est une technique gérée par l'unité
de segmentation de la MMU, utilisée sur les
systèmes d'exploitation modernes,
– qui divise la mémoire physique (dans le cas de la
segmentation pure)
– ou la mémoire virtuelle (dans le cas de la
segmentation avec pagination)
– en segments caractérisés par leur adresse de
début et leur taille (décalage).

12/15/16 120
Principes de la segmentation
• Puisque chaque segment constitue un espace d’adressage
séparé, les segments peuvent changer de longueur de
manière indépendante, sans que cela affecte les autres.

• Si une pile dans un segment requiert plus d’espace


d’adressage, elle peut l’obtenir puisqu’elle ne peut rien
atteindre d’autre dans son espace d’adressage
– Un segment peut évidemment se remplir, mais cela est rare, les
segments étant en général très grands

• Une adresse est constituée de deux parties: <numéro du


segment, déplacement (adresse à l’intérieur du segment)>

12/15/16 121
Principes de la segmentation

Dans un espace
d'adressage à une
dimension, une table
des pages qui croît
peut en chevaucher
une autre.

12/15/16 122
Principes de la segmentation
Une mémoire segmentée permet à chaque table de croître ou
de diminuer indépendamment des autres.
Exemple: compilateur

12/15/16 123
Principes de la segmentation

• un segment est une entité logique que


le programme doit manipuler

• Un segment peut contenir une


procédure, un tableau, une pile ou une
succession de variables mais
généralement il ne contient pas
d’objets de natures différentes

12/15/16 124
Considérations Pagination Segmentation
Le programmeur doit-il connaître Non Oui
la technique utilisée?
Combien y a-t-il d'espaces 1 Plusieurs
d'adressage linéaires?
L'espace total d'adressage peut-il Oui Oui
dépasser la taille de la mémoire
physique?
Les procédures et les données Non Oui
peuvent-elles être séparées et
protégées séparément?
Peut-on traiter facilement des Non Oui
tables dont les tailles varient?
Le partage de procédures entre Non Oui
utilisateurs est-il simplifié?
Pourquoi cette technique a-t-elle Pour obtenir un grand Pour permettre la séparation des
été inventée ? espace d’adressage programmes et des données dans
linéaire sans avoir à des espace d’adressage
acheter de la mémoire logiquement indépendants et
physique pour faciliter le partage et la
protection
12/15/16 125
Implantation de la segmentation
pure

• La mise en œuvre de la segmentation


diffère fondamentalement de celle de la
pagination
– Les pages sont de taille fixe alors que les
segments ne le sont pas

12/15/16 126
Implantation de la segmentation
pure
• Une mémoire physique contenant
initialement 5 segments

• (a) Le segment 1 est évincé et


remplacé par le segment 7 plus
petit

• (b) il existe un espace vide entre


les segments 7 et 2

• (c) le segment 4 est remplacé par le


segment 5

• (d) le segment 3 par le segment 6

• La mémoire est divisé en de


nombreux morceaux, certains
contiennent des segments et
12/15/16
d’autres son vides 127
Implantation de la segmentation
pure : la fragmentation externe
• (a) → (d):
phénomène du
damier
(checkerboarding)
ou fragmentation
externe, gaspillage
de la mémoire dans
les zone vides

• (e) opération de
compactage permet
cependant d’y
remédier
12/15/16 128
Implantation de la segmentation
pure
•l'adresse virtuelle issue du
processeur à la forme (segment,
déplacement).

•Le couple (segment,


déplacement) sera traduit en
adresse mémoire par le biais
d'une table de segments
contenant deux champs, limite et
base.

•La base est l'adresse de début du


segment, et limite la dernière
adresse du même segment.

•Un test est effectué pour vérifier


que l'adresse est bien dans
12/15/16 129
l'intervalle du segment.
LA SEGMENTATION AVEC
PAGINATION: PENTIUM
D’INTEL
12/15/16 130
Segmentation simple

12/15/16 131
La segmentation avec pagination

• la segmentation paginée,
– Chaque segment sera paginé.
– Autrement dit, le champ déplacement d du
couple (s, d) de l'adresse virtuelle sera
interprété comme un numéro de page et
un déplacement (p, d’).
– (s,d) = (s,p,d’)

12/15/16 132
La segmentation avec pagination

12/15/16 133
Problème de fragmentation
• Les systèmes paginés rencontrent un problème de
fragmentation interne : de la place est perdue à la fin
d'une page.
– une page entière est allouée à un processus, alors que seuls
quelques octets sont occupés. Par exemple, si l'on suppose une
taille de page de 4 Kio, un processus ayant besoin de 5 000 octets
va se voir allouer 2 pages, soit 8 192 octets, près de 40 % est
« perdu ».

• Les systèmes segmentés connaissent un problème de


fragmentation externe : des espaces entre des segments
sont trop petits pour loger de nouveaux fragments, cet
espace est donc perdu.

12/15/16 146
GESTION DE LA MÉMOIRE
DU PROCESSUS LINUX

12/15/16 147
Introduction
• Nous allons nous intéresser à toutes les techniques permettant
de gérer avec plus ou moins de précision l'espace mémoire d'un
processus.

• Nous commencerons par les principes d'allocation de mémoire


dynamique. Ces mécanismes sont relativement classiques, peu
différents des autres systèmes d'exploitation en ce qui concerne
le programmeur applicatif.

• Par contre, la bibliothèque GlibC offre des possibilités puissantes


pour le débogage, en assurant un suivi de toutes les allocations
ou en permettant d'insérer notre propre code de surveillance
dans le corps même des routines de gestion de la mémoire.

12/15/16 148
Les variables utilisées dans un
programme C
• Les variables utilisées dans un programme C peuvent
être allouées de diverses manières :
– Les variables globales ou les variables déclarées statiques au
sein des fonctions sont allouées une fois pour toutes lors du
chargement du programme.

– Les variables locales et les arguments des fonctions voient


leurs emplacements réservés dans la pile lors de l'invocation
de la fonction.

– Les variables dynamiques sont allouées explicitement par


l'intermédiaire des routines que nous allons étudier, à travers
des pointeurs sur les zones réservées.

12/15/16 149
Les variables utilisées dans un
programme C
• Le fait d'employer des variables dynamiques complique quelque peu la
programmation, puisqu'il faut les manipuler au travers de pointeurs. De
plus, elles doivent être allouées manuellement avant toute utilisation.
Pourtant, il est nécessaire d'utiliser ces variables dans plusieurs cas :

– Lorsqu'on ne connaît pas la taille des variables lors de la compilation (par exemple
une table contenant un nombre fluctuant d'éléments).

– Lorsqu'on a besoin d'allouer une zone mémoire de taille importante, principalement


s'il s'agit d'une variable locale dans une fonction susceptible d'être invoquée de
manière récursive, risquant un débordement de pile si on l'alloue de manière
automatique.

– Lorsqu'on désire gérer la mémoire le plus finement possible, en réallouant les


zones de mémoire au fur et à mesure des besoins, ou en utilisant des
organisations des données telles que la liste chaînée, l'arbre binaire, la table de
hachage...

12/15/16 150
Utilisation de malloc( )
• Pour allouer une nouvelle zone de mémoire, on utilise généralement la fonction
malloc( ), dont le prototype est déclaré dans <stdlib.h> ainsi :
– void * malloc (size_t taille);
– L'argument transmis correspond à la taille, en octets, de la zone mémoire désirée.
– Le type size_t étant non signé, il n'y a pas de risque de transmettre une valeur négative.

• Si on demande une taille valant zéro, la version Gnu de malloc( ) renvoie un pointeur
NULL. Sinon, le système nous accorde une zone de la taille voulue et renvoie un
pointeur sur cette zone.

• Si la mémoire disponible ne permet pas de faire l'allocation, malloc( ) renvoie un


pointeur NULL.
– Il est fortement recommandé de tester le retour de toutes les demandes d'allocation.

• Le code demandant d'allouer une nouvelle structure de type ma_struct_t serait donc :

12/15/16 151
Exemple 1 malloc

• Si la machine dispose par exemple de


X Go de mémoire virtuelle,

• Une demande d'allocation de X Go en


une fois échouera. Par contre, 1024*X
demandes (ou plus) d'un Mo chacune
seront acceptées tant qu'on n'aura pas
essayé d'écrire réellement dans les
zones allouées.
12/15/16 152
Exemple 1 malloc
$Man procfs :

/proc/sys/vm/overcommit_memory This file contains the kernel


virtual memory accounting mode. Values are: 0: heuristic
overcommit (this is the default)
1: always overcommit, never check
2: always check, never overcommit
In mode 0, calls of mmap(2) with MAP_NORESERVE are not checked,
and the default check is very weak, leading to the risk of
getting a process "OOM-killed". Under Linux 2.4 any nonzero
value implies mode 1. In mode 2 (available since Linux 2.6),
the total virtual address space on the system is limited to
(SS + RAM*(r/100)), where SS is the size of the swap space,
and RAM is the size of the physical memory, and r is the
contents of the file
/proc/sys/vm/overcommit_ratio. /proc/sys/vm/overcommit_ratio See
the description of /proc/sys/vm/overcommit_memory.

12/15/16 153
Exemple 1 malloc

• $ echo « 1 » >
/proc/sys/vm/overcommit_memory

• $ echo « 40 » >
/proc/sys/vm/overcommit_ratio

12/15/16 154
Exemple 1 malloc

12/15/16 155
Exemple 2 malloc

• Si nous essayons d'utiliser les zones


allouées, par contre, le comportement
pourrait être différent !

12/15/16 156
Exemple 2 malloc

12/15/16 157
Utilisation de calloc( )

• Le prototype de calloc( ) est le suivant :


– void * calloc (size_t nb_elements, size_t
taille_element);

• Cette fonction sert principalement à allouer des


tableaux. On fournit en premier argument le
nombre d'éléments à accorder, et en second la
taille d'un élément.

• En voici un exemple extrêmement classique

12/15/16 158
Utilisation de calloc( )
• La fonction calloc() assure aussi que les zones allouées
sont initialisées avec des zéros.

• Nous n’avons aucune garantie de ce genre avec les autres


fonctions d’allocation.
– Elle est donc parfois préférée à malloc() pour s’affranchir des
problèmes d’initialisation de variables, principalement lorsqu’on alloue
dynamiquement des structures définies dans les fichiers d’en-tête
d’autres modules, et qui sont susceptibles de posséder plus de
membres que ceux qui sont utilisés par l’application.

• L’appel de calloc() permet ainsi d’initialiser toute la zone


mémoire

12/15/16 159
Exemple calloc 1

12/15/16 160
Exemple 2 calloc

12/15/16 161
Exemple 3 calloc

12/15/16 162
Utilisation de free()

• La plupart du temps, il faut libérer la


mémoire qu’on a allouée
dynamiquement. Cette libération
s’effectue en invoquant la routine free()
dont le prototype est :
– void free (void * pointeur);
– On transmet à free() un pointeur sur une zone
mémoire qui a nécessairement été attribuée
avec malloc(), calloc()

12/15/16 163
Utilisation de free()
• Une fois qu’une zone a été libérée, il ne faut sous aucun
prétexte essayer d’y faire de nouveau référence.

• De même, il ne faut pas non plus tenter de libérer


plusieurs fois de suite la même zone, même si la version
Gnu peut assurer une certaine tolérance vis-à-vis de ce
genre de bogue.

• Il faut donc se méfier de la libération naïve d’une liste


chaînée ainsi :
for (ptr = debut; ptr != NULL; ptr = ptr->suivant)
free(ptr);

12/15/16 164
Utilisation de free()

• C’est une erreur grave, car le troisième


membre de for fait référence à la zone
pointée par ptr alors même que celle-ci a
déjà été libérée. Il est nécessaire en fait de
passer par une variable intermédiaire :

for (ptr = debut; ptr != NULL; ptr = suite) {


suite = ptr->suivant;
free(ptr);
12/15/16 165
Désallocation automatique avec
alloca()
• Il existe une alternative à l’utilisation du
couple malloc()–free(), constituée par la
fonction alloca().

• Celle-ci présente le même prototype


que malloc() :
– void * alloca (size_t taille);

12/15/16 166
Désallocation automatique avec
alloca()
• Le fonctionnement est identique à celui de malloc(), mais les zones de mémoire ne
sont plus allouées dans le segment de données, mais à l’opposé dans la pile du
processus.

• Les données allouées avec alloca() sont placées dans le segment de pile du
processus.

• L’avantage principal est que les zones allouées sont automatiquement libérées
lors de la sortie de la fonction ayant invoqué alloca().

• Il n’est plus nécessaire d’appeler free(), le retour de la fonction replace le pointeur


de pile au-dessus des variables dynamiques, qui ne sont plus accessibles.

• On comprend bien d’ailleurs qu’il ne faut pas invoquer free() sur le pointeur
renvoyé par alloca(), les domaines de travail de ces deux fonctions étant
totalement disjoints

12/15/16 167
Débogage des allocations mémoire

12/15/16 168
Débogage des allocations mémoire

12/15/16 169
Débogage des allocations mémoire

• Nous allons faire deux expériences : tout d’abord,


nous essaierons deux allocations avec un petit
nombre de gros blocs, puis nous réclamerons de
nombreux petits blocs.

• Les champs qui nous intéressent dans la


commande ps sont VSZ et RSS, qui représentent
respectivement la taille totale de mémoire
virtuelle utilisée par le processus et la place
occupée en mémoire physique.
12/15/16 170
Débogage des allocations mémoire

12/15/16 171
Débogage des allocations mémoire

12/15/16 172
Débogage des allocations mémoire

• Les deux invocations successives ne


conduisent pas à la même occupation
mémoire physique.

• Le système avait profité de la première


invocation pour swapper des processus
inutilisés et il disposait alors de plus de
place dès le démarrage de la seconde
invocation.
12/15/16 173
Surveillance automatique des zone
allouée
• Il est possible de demander aux routine d’allocation
d’effectuer une surveillance des zone allouées en
définissant la variable d’environnement
MALLOC_CHECK_

• Dès que cette variable est définie, les routines d’allocation


deviennent plus tolérantes, permettant les multiples
libérations d’un même bloc
– Si MALLOC_CHECK_ vaut 1, un message est inscrit sur la
sortie d’erreur standard
– Si MALLOC_CHECK_ vaut 2, le message est inscrit puis le
processus est arrêté avec abort(à

12/15/16 174
Surveillance automatique des zone allouée

12/15/16 175
Suivi intégré des allocations et des
libérations

12/15/16 176
Exemple débordement

12/15/16 177
Exemple débordement

12/15/16 178
Exemple débordement

• Deux débordements

• Valgrind: Invalide write of size 1


– écriture d’un caractère en trop

• Valgrind: Invalide read of size 1


– Lors de l’affichage de la chaîne

12/15/16 179
Exemple fuite

12/15/16 180
Exemple fuite

12/15/16 181
Exemple fuite

12/15/16 182
Exemple fuite

12/15/16 183
Suivi intégré des allocations et des
libérations
• Les versions de malloc(), calloc(), realloc() et free() contenues
dans la GlibC permettent d’enregistrer automatiquement
toutes leurs actions dans un fichie externe.

• Ce fichier n’est pas conçu pour être lu directement par un


utilisateur mais pour être analysé automatiquement par le
script Perl /usr/bin/mtrace fourni avec la GlibC. Pour activer le
suivi, il faut appeler la fonction mtrace(), dont le prototype est
déclaré dans <mcheck.h> :
– void mtrace (void);

• Pour arrêter le suivi, on appelle muntrace() :


– void muntrace(void);

12/15/16 184
Suivi intégré des allocations et des
libérations
• Naturellement, on active souvent le suivi dès le
début de la fonction main(), et on ne le désactive
pas.
– Mais on peut ainsi retreindre le champ de l’analyse à une
fonction particulière.

• Lorsque mtrace() est appelée, elle recherche dans


la variable d’environnement MALLOC_TRACE le
nom d’un fichier sur lequel l’utilisateur a un droit
d’écriture. Si le fichier existe, il est écrasé

12/15/16 185
Suivi intégré des allocations et des
libérations

12/15/16 186
Suivi intégré des allocations et des
libérations

12/15/16 187
Suivi intégré des allocations et des
libérations
Lorsque le programme ne
présente pas de défaut,
mtrace l’indique:

12/15/16 188
Règles de bonne conduite pour
l’allocation et la libération de mémoire
I. À chaque déclaration d’un pointeur, on l’initialise avec NULL. Ceci
concerne également les membres des structures allouées
dynamiquement s’il s’agit de pointeurs.

II. Avant d’invoquer malloc(), on vérifie, éventuellement dans une


condition assert(), que le pointeur à allouer est bien NULL.

III. Après tout appel de malloc(), on s’assure qu’aucune erreur n’a eu lieu,
sinon on gère le problème.

IV. Avant de libérer un pointeur, on vérifie – également dans un assert() –


que le pointeur n’est pas NULL.

V. Dès qu’on a libéré un pointeur avec free(), on le recharge


immédiatement avec la valeur NULL.

12/15/16 189
Règles de bonne conduite pour
l’allocation et la libération de mémoire

12/15/16 190
THE END

12/15/16 191

Vous aimerez peut-être aussi