Gestion RAM : pagination et segmentation

a marqué ce sujet comme résolu.

Bonjour à tous,

J'ai lu plusieurs tutos sur la gestion de la mémoire (au sens large) et j'aimerais m'assurer que j'ai bien compris ce qu'ils expliquent. Ainsi, que pensez-vous des affirmations suivantes ?

Notion d'adresses

NB : il n'est pas ici question des adresses de réseaux (Ethernet, IP, etc.), mais des adresses qui sont utilisées lorsqu'un programme est écrit, compilé, puis exécuté avec un système d'exploitation Linux.

On distingue trois catégories d'adresses :

  1. Les adresses symboliques : elles sont manipulées par le développeur d'un programme.

Exemples : utilisation d'un pointeur en langage C ou d'un objet en C++/Java avec new (manipulation explicite d'une adresse symbolique) ou encore création d'une variable objet (sans new) ou primitive en C++/Java (manipulation implicite d'une adresse symbolique).

Dans tous les cas, l'appellation "adresse symbolique" ne désigne en fait pas une adresse, mais juste un nom de variable (objet ou bien primitive) qui contiendra une adresse logique à l'issue de la compilation. D'où le terme "symbolique".

Note : l'appellation "adresse symbolique" est donc mal choisie.

  1. Les adresses logiques : elles sont générées par le compilateur dans le fichier contenant le code-machine. Toute adresse symbolique (ie. : toute variable) se voit alors affecter une adresse logique. Plus encore : tout mot du langage (types de variables, structures itératives, structures conditionnelles, opérateurs arithmétiques, etc.) se voit affecter une adresse logique. Un processus se voit aussi affecter une adresse logique.

  2. Les adresses physiques : toute case de la RAM possède une adresse physique.

Conversion d'une adresse logique vers une adresse physique

Soit un programme appelé "A". Il a été écrit puis compilé. Maintenant, on l'exécute.

Les adresses logiques du fichier compilé doivent être converties en adresses physiques car l'OS a besoin de placer les variables, les opérateurs, les structures et tout le processus en RAM.

Exemple : dans le programme, on a : c int a = 2;. Par définition, c a est codé sur 4 octets. Le fichier compilé indique que l'adresse symbolique c a possède l'adresse logique 0x123 ("0x" = "notation en hexadécimal"). Si on exécute le programme, l'OS va stocker cette variable dans la RAM (c'est ce que font les OS dès qu'un programme est exécuté). L'OS va donc chercher à savoir où stocker cette variable dans la RAM, c'est-à-dire à quelle adresse physique.

Pour déterminer une adresse physique, l'OS va prendre l'adresse logique et y ajouter un nombre (ce nombre est appelé "base"). Cette addition donne l'adresse physique. La base est choisie de manière intelligente par l'OS.

Exemple : 0x123 + 0x789789 = <adresse_physique>, et 0x789789 est la base choisie par l'OS.

Gestion de la mémoire

Trois mécanismes

  1. Pagination
  2. Segmentation
  3. Segmentation paginée

Mécanisme de pagination

La RAM est découpée en cadres (ce sont des zones de stockage) qui font tous 4096 octets. Un cadre peut contenir 0 ou 1 page. Nous verrons un peu plus tard quand est-ce qu'un cadre contient et quand est-ce qu'il ne contient pas une page. Une page est une zone de stockage faisant également 4096 octets et, si elle est dans un cadre, elle y rentre donc pile-poil (et le remplit donc intégralement).

Toute page de la RAM est constituée de 4096 adresses physiques (ce qui signifie qu'un octet = une adresse physique). Toute adresse physique d'une page de la RAM est en fait le couple (n°_page ; offset_octets), où n°_page correspond à l'ID de la page dans la RAM et offset_octets, au déplacement (en octets) dans cette page (il permet de sélectionner tel ou tel octet plutôt qu'un autre dans cette page ; c'est-à-dire telle ou telle adresse physique plutôt qu'une autre dans la RAM).

Imaginons qu'une instance d'exécution d'un programme (= "un processus") vient d'être créée (= on a lancé un programme). Ce processus doit être stocké en RAM. Il possède obligatoirement et par définition une adresse logique de la forme (n°_page ; offset_octets). L'OS va consulter une table, la table des pages (= "bitmap") et regarder quelle est l'adresse physique où l'on doit stocker le processus (ce qui revient à dire : dans quelle page de la RAM stocker le processus). Les entrées de la bitmap sont de la forme (n°_page_logique ; n°_page_physique). Donc l'OS n'a qu'à faire correspondre le numéro de page logique du processus au numéro de page logique de la table, et il trouvera le numéro de page physique. Avec l'offset, il pourra trouver l'adresse physique où stocker le processus.

Si on a configuré la machine et l'OS pour supporter le mécanisme de swap (donc on a un disque dur qui étend la RAM ; le swap est découpé en cadres et eux-mêmes en pages de manière identique à la RAM), et que la table indique une entrée de la forme <n°_page_logique ; n°_page_physique_sur_swap>, une exception est levée : elle est appelée "défaut de page".

Si un défaut de page est levé, l'OS va chercher à ramener la page désirée (qui se situe donc dans le swap) en RAM : soit la RAM comporte un cadre vite et l'OS l'y place, soit la RAM est pleine et il faut que l'OS fasse un swapping : échanger la page du swap avec une page de la RAM (on appellera cette dernière la "page victime"). Ainsi, après ce swapping, la page victime sera située dans le swap (le disque dur), à la place de la page désirée et la page qui était sur le HDD (celle que l'on désire) sera stockée en RAM, à la place de la page victime.

L'idée, pour ce faire, c'est de choisir la page de la RAM qui sera utilisée le plus tard possible : plusieurs algorithmes existent : LRU, FIFO, LIFO, etc.

Mécanisme de segmentation

La segmentation n'a rien à voir avec la pagination. La pagination permet de structurer la RAM en blocs de taille fixe (les cadres, et qui d'ailleurs contiennent 0..1 page). La segmentation, elle, permet de structurer les processus.

En effet, tout processus est découpé en segments qui possèdent chacun une taille qui leur est propre, et chacun d'eux est indépendant des autres. La RAM n'est pas découpée en segments. En fait, elle n'est pas du tout structurée : elle n'est pas du tout découpée en quoi que ce soit.

Le processus qu'on a lancé va être stocké dans la RAM de la façon suivante… Son adresse est constituée de : (n°_segment ; offset_octets). L'OS possède une table, la table de la segmentation, dont les entrées sont de la forme : <adresse_physique_segment ; taille_du_segment>. L'OS va trouver le segment n°<n°_segment> dans la table (en comptant les entrées à partir de la toute première entrée, incluse). Une fois le numéro trouvé, l'OS va regarder quelle est l'adresse physique du segment dans la RAM (adresse_physique_segment). Puis, l'OS va s'assurer que offset_octets est strictement inférieur à taille_du_segment. Si c'est le cas, l'OS peut stocker le programme à cette adresse physique de la RAM. Sinon, une erreur est générée (car on essaierait alors de stocker un processus à un offset plus grand que sa taille !).

==============

Je n'ai pas fini d'écrire, il me faut encore parler du swap dans le cas de la segmentation notamment :)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte