Allocateur mémoire en Java TP4 et TP5 : Pratique
Transcription
Allocateur mémoire en Java TP4 et TP5 : Pratique
Allocateur mémoire en Java TP4 et TP5 : Pratique V.Marangozova-Martin, Ludovic Démontes 1 L’allocation de mémoire L’utilisation de la mémoire est indispensable dans toute exécution de programme. Quand un programme est lancé, afin de créer le processus qui a son tour manipulera des données, le système alloue une zone mémoire. Quand le processus termine, sa mémoire est libérée et peut être utilisée (allouée) par d’autres processus. De la même manière, quand un programmeur a besoin d’initialiser une donnée pendant l’exécution de son programme, il doit d’abord s’assurer que la variable va pouvoir être placée en mémoire 1 . Pour cela, il doit demander (allouer) de la mémoire pour sa variable. Une fois le travail avec la variable terminé, le programmeur doit libérer la mémoire afin de la rendre disponible pour d’autres variables. En C ou C++ les opérations d’allocation/libération sont explicites dans le programme (malloc/free). En Java, l’allocation/libération est gérée implicitement par la JVM. En effet, lors de la création d’un nouvel objet (new), la JVM alloue la mémoire nécessaire. La libération de la mémoire est faite par le ramasseur de miettes (garbage collector ) qui vérifie si un objet est encore utilisé et si non, récupère sa mémoire. Un allocateur mémoire est le gestionnaire qui a accès à la mémoire et qui tient compte des zones de mémoire libres et des zones mémoire occupées. C’est ce gestionnaire qui fournit les opérations d’allocation/libération de mémoire qui sont utilisées par le système/l’utilisateur. 2 Objectif du TP Dans ce TP, vous avez pour objectif d’implémenter un allocateur simple qui gère la mémoire physique dont la taille est définie de manière statique. 1 Il s’agit surtout des cas où on manipule des pointeurs. 1 Miage3, 2009-2010 2 L’allocateur devra : – connaître l’état de la mémoire i.e les zones libres et les zones occupées ; – allouer des zones de mémoire lorsque le système ou l’utilisateur les demande ; – libérer des zones de mémoire utilisées lorsque le système ou l’utilisateur n’en a plus besoin. 3 Réalisation L’allocateur sera implémenté par une classe Allocateur qui aura des attributs représentant la mémoire physique, ainsi que deux méthodes alloc et free. Cette classe devra être réalisée en suivant les étapes décrites ci-dessous. 3.1 Représentation de la mémoire La mémoire physique sera représentée dans la classe Allocateur par un attribut de type Memoire. La classe Memoire contiendra deux choses : les structures de données qui permettent de gérer la mémoire, ainsi que les structures qui représentent l’espace mémoire utilisable. class Memoire { public static int SIZE = ...; // taille memoire en octets private BitSet bitset ; // structure de gestion private StringBuffer mainmemory ; // la memoire disponible ... // methodes } L’attribut SIZE est à fixer à votre convenance, il représentera la taille en octets de la mémoire utilisable. L’attribut bitset représentera l’état de la mémoire. Cet attribut sera un vecteur de bits, chaque bit étant rattaché à une zone mémoire différente. Si on décide de découper la mémoire en zones de 10KO, alors bitset contiendra SIZE/10KO bits. Un bit positionné à 1 indiquera que la zone est occupée (allouée), alors qu’un bit à 0 indiquera que la zone est libre2 . L’attribut mainmemory, un "tableau" de caractères, représente la mémoire allouable. Un caractère étant encodé sur un octet, la taille de la mémoire correspond au nombre de caractères présents dans mainmemory. Il faut veiller à ce que cette taille soit cohérente avec SIZE. 2 Ceci devrait vous rappeler la pagination. Miage3, 2009-2010 3 Question 1 : Implémentation de la classe Memoire Créer la classe Memoire et écrire son constructeur afin d’initialiser les attributs de manière cohérente. Quelle doit être la taille du bitset ? Comment doit-il être initialisé ? Quelle est la taille de mainmemory ? Si vous faites correspondre 1 bit de la bitset à 1 octet en mémoire, quelle sera la taille de la bitset ? Et si vous faites correspondre 1 bit à une zone de 10 octets, de 20 octets, de 1KO ? Que se passe-t-il au niveau fragmentation ? 3.2 Implémentation des méthodes alloc et free Nous allons implémenter les stratégies d’allocation en zones contiguës. La méthode alloc prendra en paramètre le nombre d’octets demandés. Elle retournera comme résultat un identifiant de la zone allouée. Cet identifiant sera utilisé plus tard pour la libération de la zone. SI l’allocation échoue, alloc retournera −1. La méthode free prendra deux paramètres afin de libérer une zone mémoire : l’identifiant d’une zone allouée et sa taille. Elle retournera 0 en cas de réussite et −1 sinon. class Allocateur { private Memoire memory ; ... // methodes public Allocateur () { /* ... TO DO ... */ } public int alloc ( int nbOctets ) { /* ... TO DO ... */ } public int free ( int idZone , int nbOctets ) { /* ... TO DO ... */ } } Question 2 Que doit faire le constructeur de la classe Allocateur ? Ecrire ce constructeur. Question 3 Imaginons que la mémoire est vide. Comment doit être traitée la demande alloc(10) ? Quelle partie de la mémoire sera occupée ? Que se passera-t-il avec le bitset ? Question 4 Imaginons que la mémoire a été utilisée pendant un certains temps et a déjà "subi" plusieurs allocations et libérations. Elle sera typiquement composé de zones libres et de zones occupées qui s’intercalent. Nous avons vu en Miage3, 2009-2010 4 cours que pour allouer une nouvelle zone il existe plusieurs stratégies. Quelles sont les trois stratégies existantes ? Question 5 Comment doit être traitée la demande alloc(10) dans le cas général (mémoire non vide) avec une stratégie first fit ? Comment trouverezvous la zone adéquate ? Ecrire la méthode alloc. Question 6 Pourquoi la méthode free doit prendre en paramètre la taille de la zone ? Que se passerait-il si ce paramètre est omis ? Question 7 Comment doit être traitée la demande free(10, 25) ? Que se passe-t-il au niveau du bitset ? Ecrire la méthode free. 4 Et la synchro dans tout cela ?... Vous avez écrit votre allocateur et il marche très bien dans le cas d’un programme qui fait des appels à alloc et free. Que se passe-t-il, par contre, si plusieurs threads appellent simultanément ces méthodes ? Comment corriger le problème ? 5 Un peu de reflexion... Question 8 Nous avons présenté la mémoire par la classe Memoire. D’après vous, les données permettant la gestion de la mémoire (SIZE et bitset) doiventils être gardés en mémoire ? EN d’autres termes, les structures pour la gestion de la mémoire doivent-ils être stockées en mémoire ? Que cela implique-t-il en ce qui concerne la taille de la mémoire disponible pour les programmes ? Question 9 Qui est sensé manipuler les structures de gestion de la mémoire ? Le système ou un programme utilisateur ?