Vous êtes sur la page 1sur 2

TD Systèmes d’exploitation


Gestion de la mémoire
L3 UPJV
Septembre 2021

Allocation mémoire dynamique


Dans un processus, il y a généralement 4 zones de mémoires :
— la zone text, où se situe le code binaire exécutable ;
— la zone data, où sont stockées les variables statiques (globales entre autres) du programme ;
— la zone stack, qui est la pile d’exécution du programme, où se situent les variables automatiques
(locales) ainsi que les adresses de retours des appels de fonctions ;
— enfin la zone heap (tas en français), où sont stocké les données dynamiques de l’application, en
l’occurrence les mallocs d’un programme C, ou les objets d’un programme Java. Cette zone est
communément appelée mémoire dynamique.
C’est à la gestion de cette dernière que nous allons nous intéresser.
Au début du programme, cette zone est entièrement libre, et au fur et à mesure que le programme
avance, des morceaux de celle-ci seront réservés (malloc) pour stocker les données du programme, ou
libérés (free). Pendant l’exécution du programme, la zone mémoire devient donc morcelée, on dit aussi
fragmentée, il y a une succession de bloc alloué et libre dont les tailles dépendent de l’historique des
allocations (voir figure 1 1 ).


On appelle fuite mémoire, le fait que dans un programme, la mémoire associé à des données
dynamiques qui ne sont plus utilisées, n’est jamais libérée (malloc sans free). Cela peut
être problématique, notemment pour les programmes systèmes qui ne s’arrètent jamais : à
un moment donné la mémoire peut être pleine, et il faut alors redémarrer le système. Les
programmes qui utilisent des gestions automatiques de la mémoire dynamique (garbage
collector ), par exemple ceux qui sont écrit en Java, ne sont pas concernés par ce problème.

Politique d’allocation mémoire


Quand un nouveau bloc mémoire doit être alloué, il faut donc déterminer où le bloc sera mis dans
la mémoire. Les allocations se font de manières contiguës : le bloc est affecté au bloc libre qui suit un
autre bloc alloué, l’espace restant, s’il y en a, constituant un nouveau bloc libre. Il faut donc définir
une stratégie de sélection du bloc libre qui sera choisi pour l’allocation. On distingue trois politiques
principales :
— First-fit : on choisit le premier bloc libre qui est de taille suffisante ;
— Best-fit : on choisit le bloc libre dont la taille est la plus proche de la taille demandée ;
— Next-fit : comme pour le First-fit, si ce n’est que l’on commence la recherche à partir de la
dernière allocation.
La figure 1 illustre ces trois politiques.
À l’inverse, quand un bloc mémoire est libéré, l’espace à nouveau libre est fusionné avec les espaces
libres adjacents, augmentant la taille du bloc libre.
1. Extrait de Operating Systems, Internals and Design Principles, Willam Stalling, Prentice Hall.
Figure 1 – Exemple d’allocation mémoire d’un bloc de 16Mo.

Exercice 1 Considérer la suite des allocations et libérations de mémoire suivante :


char *a, *b, *c, *d, *e, *f, *g, *h, *i, *j;

a=malloc(300); b=malloc(200); c=malloc(250); free(b); d=malloc(100);


free(a); e=malloc(250); f=malloc(400); free(c); g=malloc(150);
h=malloc(100); free(d); free(h); i=malloc(200); free(g); free(e);
j=malloc(100); free(f); free(j); free(i);
Illustrer, par des schémas similaires à la figure 1, l’évolution de l’occupation de la mémoire pour chacune
des trois politiques d’allocation. La mémoire a une taille de 1000.

Exercice 2 On constate que la mémoire est fragmentée. Une conséquence est que bien qu’il y ait globa-
lement assez de mémoire libre, une allocation est impossible parce qu’il n’y a pas de bloc libre assez grand.
Une solution serait dans ce cas, de compacter tous les blocs alloués en une seule zone afin de créer un
bloc libre avec la mémoire restante.
Expliquer pourquoi cela n’est pas possible dans le modèle de programmation du langage C ?

Mise en oeuvre
Exercice 3 Pour chacune des politiques, vous devez réécrire le code de la fonction malloc qui retourne
l’adresse de la mémoire allouée, et qui gère la liste des blocs libres.
Pour cela, vous disposez d’une constante globale HEAP BEGIN de type void *, qui contient l’adresse
du premier octet de la zone heap. De même vous avez la constante HEAP END qui contient l’adresse du
dernier octet de la même zone.
Avant d’écrire vos fonctions, vous aurez besoin de définir la structure qui permet de chaı̂ner les blocs
libres entre eux.

Vous aimerez peut-être aussi