Aller au contenu principal

Gestion de la mémoire

Progression

#Gestion de la mémoire

Pour un processus, la mémoire semble linéaire, privée et abondante. En réalité, le noyau et l'unité de gestion mémoire (MMU) orchestrent une traduction permanente entre les adresses virtuelles vues par le programme et les adresses physiques réelles.

#1. Pagination et tables de pages

La mémoire virtuelle est découpée en pages de taille fixe (4 KiB sur la plupart des architectures courantes). Chaque page virtuelle possède une entrée dans une table de pages qui indique où se trouve le contenu en mémoire physique, ainsi que les permissions (lecture, écriture, exécution). Si une page n'est pas présente, l'accès déclenche un défaut de page : le noyau suspend le processus, charge la page depuis le disque (fichier mappé ou zone de swap), met à jour l'entrée puis reprend l'exécution. Les processeurs modernes ajoutent un cache de traduction (TLB) pour éviter de relire la table à chaque accès.

#2. Layout et allocation

L'espace virtuel d'un processus classique se compose d'une zone texte (code, en lecture seule), d'une zone de données initialisées, d'un segment bss (données zéro), d'un tas (heap) qui grandit vers les adresses hautes via brk ou mmap, et d'une pile (stack) qui grandit vers le bas. malloc et free ne font pas apparaître ou disparaître des pages physiques instantanément : ils gèrent des blocs dans le tas, tandis que le noyau fournit ou récupère des pages entières selon les besoins. C'est pour cela qu'un programme peut conserver une consommation apparente élevée même après avoir libéré des structures volumineuses.

#3. Partage maîtrisé

La mémoire virtuelle facilite le partage sans compromettre la sécurité. Deux processus peuvent mapper le même fichier en lecture seule (mmap avec MAP_SHARED) et bénéficier d'une mise à jour simultanée. Les bibliothèques partagées sont chargées une seule fois en mémoire physique, puis référencées par chaque processus qui les utilise. fork exploite également la stratégie copy-on-write : tant que parent et enfant lisent seulement les pages héritées, elles restent partagées. La duplication n'intervient qu'au moment de la première écriture.

cc
1int fd = open("archive.bin", O_RDONLY);2void *view = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);3process(view);4munmap(view, size);

#Atelier

Écrivez un programme qui alloue 500 Mo, pré-initialise les données, appelle fork, puis mesure le temps de duplication lorsque parent et enfant modifient chacun une moitié du tableau. Instrumentez le tout avec pmap et /proc/self/smaps pour visualiser quelles pages sont partagées, privées ou swappées. Vous observerez concrètement l'effet du copy-on-write et des fautes de page.