Gestion de la mémoire

 

 

Vous n'avez pas encore mal à la tête ?

Cela devrait venir !

 

Introduction:

Windows est 32 bits. Cela signifie que théoriquement, on pourrait avoir jusqu'à 4 gigas accéssibles en mémoire (de 0x00000000 à 0xFFFFFFFF).

Or il parait plutôt difficile de faire tenir 4 gigas en mémoire vive ne faisant que 128 à 512 Meg.

 

La solution: Le mode protégé...

Un processus a alors son espace de mémoire privée d'adresses virtuelles.

- Privé car aucun autre processus ne pourra accéder à cet espace.

- Virtuelle car tous les processus peuvent accéder à une zone mémoire allant de 0x00000000 à 0xFFFFFFFF, mais (du fait que la mémoire est privée), la valeur trouvée dans une adresse d'un processus n'aura rien à voir avec la valeur de la même adresse d'un autre processus (ou alors, se serait un pur hazard).

 

Or Windows est multi-processus. Cela va donc signifier que chaque processus doit avoir 4 gigas de mémoires...

Pour pouvoir gérer les 4 gigas multipliés par les n processus qui tournent dans le peu de mémoire réellement présent, Windows découpe l'espace de mémoire d'un processus en pages. Ces pages pourront se trouver soit en mémoire, soit sur disque qui est le seul support suffisement rapide (!) et possédant la place nécessaire (les données pourront alors être stockées par exemple dans le fichier de swapping).

Sur disque ou en mémoire ?

Le principe étant assez simple, plus une page est utilisée, plus longtemps elle restera en mémoire.

Ce sera à Windows de s'occuper de faire l'opération de transfert entre l'espace d'adressage virtuel et l'espace d'adressage réel.

Dans le cas d'un processus, tout le code ne sera pas chargé en mémoire, mais uniquement quelques pages. Le code étant extrait directement de l'exécutable au fur et à mesure des besoins. En aucun cas, le code ne sera stocké dans le fichier de swapping car il ne sera jamais modifié, il serait donc dommage de dupliquer le code !

Les données non modifiées du code seront elles aussi extraitent du fichier exécutable. Par contre, si celles-ci sont modifiées, alors elles passeront dans le fichier de swapping et seront toujours restaurées en mémoire via le fichier de swapping.

A savoir:

Sur les 4 Gigas, 2 gigas sont réservés pour le programme, les 2 autres servant au système.

 

Et la gestion de la mémoire dans tout cela ?

Et bien il y a deux cas à voir:

- Un processus qui a besoin de mémoire: il devra toujours la réserver, même si on est soi-disant seul à utiliser l'espace mémoire virtuelle pour parexemple prendre en compte le multi-thread.

- Un processus qui veut accéder au contenu de la mémoire d'un autre processus ! En principe, ce n'est pas possible d'après ce que l'on vient de dire, mais Microsoft a pensé à tout, et cela devient donc possible via quelques fonctions spécifiques.

A tout ce qui vient d'être dit se rajoute aussi le fait que Windows évolue dans le temps. Et par conséquent, il existe de nombreuses fonctions dont certaines sont obsolètes...

 

Classification des fonctions d'allocations de mémoires suivant le besoin:

Vous avez besoin d'allouer moins de 64 ko de mémoires:

- On utilisera les fonctions malloc(), calloc(), realloc(), free() (fonction similaire à celle du DOS, d'Unix ou ST...) si vous développez en C. (Le document pointé ici correspond à un document que j'ai créé dans la section Unix et contient d'autres fonctions permettant la manipulation des données.)

- Ou enfin HeapAlloc()

 

Vous avez besoin d'un peu plus que 64 ko:
VirtualAlloc
Réserve ou alloue une partition dans l'espace d'adresses virtuelles d'un processus. Cette fonction convient beaucoup aux allocations importantes de mémoire ( > 64 Ko ). Pour les "petites" allocations, il est préférable d'utiliser les fonctions de tas (HeapAlloc et malloc). Pour libérer la mémoire allouée avec VirtualAlloc, il convient d'utiliser VirtualFree.

VirtualQuery
Etant donné un pointeur de valeur quelconque, renvoie l'état, la taille, la position, les protections de la partition de mémoire à laquelle il appartient. Les différents états sont : non alloué, non alloué mais réservé, alloué.

GetModuleHandle
Avec NULL passé en paramètre, le handle renvoyé est l'adresse de chargement du fichier exécutable. Cette zone est accessible en lecture, vous pourrez y lire l'en-tête EXE du fichier.

IsBadReadPtr, IsBadWritePtr
Teste si le processus a droit de lecture / d'écriture sur la zone mémoire pointée. Le pointeur passé en paramètre peut avoir n'importe quelle valeur.

CopyMemory
Copie une zone mémoire vers une autre.

Voir le chapitre sur la gestion de l'espace d'adresses virtuelles

 

Vous avez besoin d'énormement de mémoire (pour la vidéo par exemple) ou d'échanger des données entre processus:

Mapping de fichiers en mémoire. C'est cette méthode qui est utilisée pour faire des échanges de données entre processus.
CreateFileMapping ()
Crée un file mapping object pour un fichier donné. Cet objet peut être ouvert par d'autres applications avec OpenFileMappingObject().

MapViewOfFile()
Mappe la totalité ou une partie d'un fichier dans l'espace d'adresses virtuelles du processus courant. Utilisez UnmapViewOfFile() pour libérer l'espace d'adresses virtuelles.

Voir chapitre sur le mapping.

 

Manipulation de la mémoire d'un autre processus
VirtualQueryEx
Renvoie l'état, la taille, la position, les protections d'une partition de mémoire de n'importe quel processus.

CreateRemoteThread
Crée un thread dans l'espace virtuel d'un autre processus. Le code du thread doit exister dans l'espace virtuel du processus.

ReadProcessMemory, WriteProcessMemory
Permet de lire et d'écrire dans la mémoire de n'importe quel processus.

 

Gestion de ma mémoire à la sauce Windows 3.1 et peut-être aussi dans les versions antérieures...

Enfin GlobalAlloc qu'il ne faut normalement plus utiliser sauf...

Cette fonction date au moins de Windows 3.1 et est donc un peu dépassée. Cependant, vous pouvez encore en avoir besoin pour le presse papier (étudié dans un autre chapitre) ou encore pour le DDE (je ne suis pas certain de vouloir me lancer sur ce sujet...).

...

 

Allocation mémoire en C++:

A noter qu'il existe une commande d'allocation mémoire en C++: new(), delete().