Mémoire virtuelle
Introduction
La notion de mémoire virtuelle n'est pas récente, elle date des années 1960.
La
définition
en a été donnée au début du chapitre.
Les adresses virtuelles sont celles référencées par un processus en cours d'exécution.
Elles dépendent en principe des capacités d'adressage du processeur, indépendamment de la mémoire physiquement installée.
L'ensemble des adresses virtuelles possibles est l'espace des adresses virtuelles ou espace d'adressage.
Les adresses physiques au contraire correspondent à la mémoire réellement installée.
Un programme qui s'exécute doit être placé en mémoire physique.
Or d'une part, la mémoire physiques peut ne pas pouvoir contenir toute la mémoire virtuelle d'un processus, d'autre part, dans un contexte de multiprogrammation, plusieurs programmes sont candidats pour être chargés simultanément en mémoire physique.
Il faut donc mettre en œuvre une politique d'allocation de la mémoire réelle.
Cette politique d'allocation est fondée sur le découpage de la mémoire physique et de la mémoire virtuelle en blocs de tailles égales ou différentes, appelés segments ou pages.
Il existe trois catégories de méthodes d'allocation, appelées segmentation, pagination ou une combinaison des deux : segmentation-pagination.
La figure ci-dessous montre l'évolution des politiques d'allocation de la mémoire physique, d'un système dédié à un seul utilisateur à une segmentation-pagination avec multiprogrammation.

Si une partie d'un processus en cours d'exécution doit se trouver en mémoire centrale, le reste doit se trouver en mémoire secondaire, en général sur disque, où il est aussi découpé en blocs de la même taille.
Le S.E. doit pouvoir à tout instant établir une correspondance (par exemple en maintenant continuellement à jour une ou plusieurs tables) entre les blocs de la mémoire virtuelle de chaque processus et les blocs de la mémoire physique où ils sont stockés, et doit aussi pouvoir détecter si un bloc de mémoire virtuelle n'est pas présent en mémoire centrale (par exemple par un bit de "présence/absence"), comme illustré ci-dessous.
Ce mécanisme doit être le plus rapide possible pour ne pas ralentir le traitement.
L'efficacité du système dépend aussi de la taille des blocs : plus les blocs sont petits, plus les tables de correspondance sont volumineuses.
Inversement, plus les blocs sont importants, plus les temps de transfert d'un bloc de la mémoire centrale au disque (ou inversement) sont longs.
En pratique, chaque processus a sa table des blocs, qui est stockée de préférence dans la partie de la mémoire réservée au système.
L'adresse du début de la table est stockée dans une zone qui fait partie du contexte du processus.
Lorsqu'un processus est rendu "actif", cette adresse est chargée dans un registre "de base".
Chaque élément de la table des blocs doit donc contenir au minimum les informations suivantes :
-
le bit de présence/absence du bloc virtuel en mémoire réelle (voir ci-dessous :
défaut de bloc),
-
la longueur du bloc (inutile si les blocs sont tous de même taille, ce qui est le cas de la pagination),
-
l'adresse de stockage de ce bloc en mémoire physique,
-
un bit de modification,
Format des adresses virtuelles
Toutes les adresses virtuelles dans le programme sont formées de deux parties : le numéro de bloc de la mémoire virtuelle et le déplacement (nombre d'octets) par rapport au début du bloc.
La forme générale d'une adresse virtuelle av est donc :
av = (nb, d)
où nb est le numéro de bloc, et d le déplacement.
Calcul d'une adresse physique
Lorsque le processeur rencontre l'adresse virtuelle (nb, d), il recherche l'élément nb correspondant dans la table des blocs du processus actif.
Si le bloc est absent, il y a défaut de bloc.
Si le bloc est présent, l'adresse physique est égale à la somme de l'adresse physique du bloc en mémoire réelle et du déplacement dans le bloc :
ap = TableBloc[av.nb].adr + av.d
Défaut de bloc
Si le bit de présence/absence du bloc est à 0 (bloc absent de la mémoire centrale), il y a défaut de bloc.
Dans ce cas, le bloc doit être chargé à partir de la mémoire secondaire (disque), ce qui prend un certain temps.
De plus il faut trouver une place dans la mémoire centrale pour stocker le nouveau bloc.
Si aucune place n'est disponible, il faut remplacer un bloc déjà chargé par le nouveau bloc.
Avant d'écraser un bloc, il faut le sauvegarder en mémoire secondaire (disque) s'il a été modifié depuis son dernier chargement.
Cette indication est fournie par un bit d'écriture, mis à 1 dès que le contenu du bloc est modifié (écriture d'une information en mémoire physique contenant ce bloc).
Protection
La protection des différents utilisateurs est beaucoup plus difficile à effectuer que précédemment.
En particulier, un seul ou deux registres limites ne suffisent plus.
En effet, les blocs ne sont pas contigus dans la mémoire physique.
A chaque calcul d'adresse physique, il faut donc vérifier que le déplacement ne dépasse pas la longueur du bloc, stockée dans la table des blocs.
La figure suivante résume les différentes phases du calcul de l'adresse physique :
Calcul de l'adresse physique
Mémoire linéaire - Mémoire segmentée
Lorsque toutes les adresses virtuelles sont exprimées par rapport au début du programme, on dit que la mémoire virtuelle est linéaire.
Lorsque, au contraire, le programme est formé de plusieurs parties (segments), sans aucun rapport entre eux, et que toutes les adresses virtuelles sont exprimées par rapport au début d'un segment, on dit que la mémoire est segmentée.
Pagination simple d'une mémoire virtuelle linéaire
Principe de la pagination simple
Le nombre d'octets Np d'une page est toujours une puissance de 2 : 2p.
La mémoire physique et la mémoire virtuelle sont découpées en pages de la même taille.
Soit Nr et Nv le nombre de pages de la mémoire réelle et de la mémoire virtuelle.
Nr et Nv sont aussi des puissances de 2 :
Np = 2p ; Nr = 2r ; Nv = 2v
Considérons par exemple un processeur d'adressage sur 16 bits.
Cela signifie qu'il peut générer une adresse virtuelle sur 16 bits (donc désigner un parmi 65536 octets).
Supposons aussi que les pages (physiques ou virtuelles) soient formées de 4096 octets (= 212).
Cela signifie que le déplacement dans une page occupe 12 bits.
Considérons l'adresse virtuelle suivante : 1100 1101 1001 0001, ou, en hexadécimal : 0xCD91.
Elle peut être mise sous la forme av = (nv, d) :
numéro de la
page virtuelle
|
déplacement |
1100 |
1101 1001 0001 |
Elle se trouve donc dans la page virtuelle 12.
Supposons enfin que cette page virtuelle se trouve stockée dans la page physique 7.
Pour calculer l'adresse physique correspondante, il faut remplacer le numéro de la page virtuelle nv par le numéro de la page physique np, soit ap = (np, d), qui peut être écrite :
numéro de la
page physique
|
déplacement
|
0111 |
1101 1001 0001 |
Table des pages en mémoire
La table des pages correspond à la table des blocs citée plus haut, pour chaque processus.
La longueur n'a pas à être stockée puisque toutes les pages sont de même taille.
Elle peut être stockée en mémoire centrale.
Néanmoins, cette solution est très pénalisante.
En effet, chaque accès à un octet de la mémoire physique par le programme nécessite au préalable le calcul de l'adresse physique, qui doit lui-même lire en mémoire l'adresse physique de la table.
Il s'ensuit que l'accès utile à la mémoire nécessite deux accès réels, et diminue donc la vitesse de moitié.
Utilisation de mémoire-cache
La mémoire-cache est une mémoire d'accès beaucoup plus rapide que la mémoire principale (au moins d'un facteur 10).
Si la table de correspondance des pages réelles et virtuelles y est logée, le temps de calcul de l'adresse physique est beaucoup moins pénalisé.
Cependant, la mémoire-cache est assez coûteuse et une taille suffisante pour contenir la totalité de la table de correspondance est prohibitive.
Utilisation d'une mémoire associative
Une mémoire associative est une mémoire dans laquelle chaque numéro de page physique est l'indice de la table et contient le numéro de la page virtuelle qui y est stockée.
De plus tous les éléments de cette table sont consultés simultanément, donc la recherche est très rapide.
Cette méthode a les mêmes avantages et les mêmes inconvénients que la mémoire-cache : rapidité mais coût élevé.
La figure suivante illustre le mécanisme de calcul de l'adresse physique :

Solution mixte
La solution souvent adoptée consiste à coupler les deux solutions : table de correspondance à la fois dans la mémoire associative et dans la mémoire principale :

La mémoire associative ne contient qu'une petite partie des pages, celles qui ont été utilisées le plus récemment.
En effet, on sait, par le
principe de proximité
exposé plus loin, que la probabilité de réutilisation d'une page récemment accédée est de 90 à 95 %.
En cas d'échec, la recherche de la page demandée est alors effectuée dans la mémoire principale.
Si cette dernière prend plus de temps, elle est suffisamment peu fréquente pour ne pas pénaliser le système.
Partage de page
Les pages contiennent soit du code exécutable (elles sont appelées pages procédures) soit des données (pages données).
Le partage de pages de code par différents processus est appelé la réentrance.
Elle permet d'économiser beaucoup de place mémoire.
En revanche ces pages de procédures doivent être protégées en écriture.
Des pages de données peuvent aussi être partagées.
Si ce sont des constantes, elles doivent aussi être protégées en écriture.
Le partage de pages de données est un moyen très rapide et efficace de communication entre processus.
Hyperpagination
Introduction
Plus les mémoires virtuelles augmentent, plus les tailles des tables de correspondance augmentent, elles aussi, et elles finissent par encombrer l'espace mémoire physique.
C'est pour remédier à cet inconvénient qu'est utilisée l'hyperpagination.
La mémoire virtuelle d'un processus est toujours linéaire.
Elle est découpée en hyperpages de tailles très importantes de 10 à 100 pages).
Adresse virtuelle et tables de correspondance
Les adresses virtuelles sont formées de trois champs :
-
le numéro de l'hyperpage nhp,
-
le numéro np de la page dans l'hyperpage,
-
le déplacement d dans la page :
ap = (nhp, np, d)
La table des hyperpages est en mémoire centrale.
Chacun de ses éléments pointe vers une table des pages de l'hyperpage qui ne contient que les pages réellement existantes.
Ainsi, seuls les programmes très volumineux ont des tables de correspondance importantes.
Calcul des adresses physiques
La conversion des adresses virtuelles en adresses physiques est schématisée ci-dessous :

Segmentation
Introduction
La segmentation est tout à fait analogue à la pagination.
Le programme est découpé en parties qui ne sont pas forcément de la même taille.
Contrairement à la mémoire virtuelle linéaire ou toutes les adresses possibles constituent une suite d'adresses contiguës de 0 à l'adresse maximale, les adresses virtuelles recommencent à 0 pour chaque segment et n'ont aucune relation d'ordre d'un segment à l'autre.
Protection
Le découpage en segments rend possible un contrôle d'accès très poussé.
On retrouve classiquement quatre types d'accès à un segment bien connus, représentés dans le tableau ci-dessous :

Si un processus a un droit d'accès à la fin (Append), il est autorisé à ajouter des informations en fin de segment mais ne peut modifier les informations déjà existantes.
Chaque processus possède une combinaison (valide) de ces droits pour chacun de ses segments.
Adresse virtuelle et table de correspondance
Les adresses virtuelles sont constituées de deux parties : le numéro du segment et l'adresse dans ce segment (qui est le déplacement).
Le calcul de l'adresse physique est obtenu en remplaçant dans l'adresse virtuelle le numéro de segment par son adresse physique et en lui ajoutant le déplacement.
La table des pages est remplacée par la table des segments.
Chacun de ses éléments est de la forme suivante :

Calcul des adresses physiques
Le procédé de calcul est semblable à ceux étudiés précédemment.
Segmentation - Pagination
Introduction
Les avantages des deux techniques sont rassemblés dans cette solution, dont la mise en application n'est pas simple.
Les segments ont l'avantage de correspondre à des découpages logiques, et il est tout à fait compréhensible que plusieurs processus partagent un même segment.
Le découpage d'un programme en pages est arbitraire et le partage de pages n'est pas très justifié.
L'inconvénient majeur d'un segment est la nécessité pour lui d'occuper un espace mémoire contigu, qui peut être volumineux.
Le découpage des segments en pages résout ce problème et en rend l'utilisation beaucoup plus souple.
Adresse virtuelle et tables de correspondance
L'adresse virtuelle est alors constituée d'un numéro de segment ns, d'un numéro de page dans ce segment np, et d'un déplacement dp dans la page.
En réalité, comme précédemment, le numéro np, et le déplacement dp peuvent être remplacés par un nombre unique qui est le déplacement dans le segment ndp.
La mémoire virtuelle est décrite par une table des segments dont chaque élément pointe vers une table des pages de ce segment.
Calcul des adresses physiques
Le calcul des adresses physiques commence par une recherche du segment, puis de la page, puis de l'adresse de la page physique correspondante, à laquelle est ajouté le déplacement d, comme indiqué ci-dessous
Calcul de l'adresse physique à partir de l'adresse virtuelle en mémoire segmentée
Dernière mise à jour : 07/11/2001