Partage de mémoires ou file mapping

 

 

Tout comme Unix, Microsoft permet de partager de la mémoire entre différents processus, pour échanger de petites ou grandes quantités de données. Il est créé par le premier processus puis ouvert par les n processus suivant et chacun en mappe une partie ou son intégralité dans son espace d'adressage.Attention ce systèmes ne prévois pas de mécanisme d'exclusion mutuel, il faudra les prévoir en plus. Si on passe NULL à la place du nom du fichier les donnés seront stockées dans le swap du système et seront détruites à la fermeture du fichier.

 

Les fonctions disponibles:

Pour créer un espace de mémoire partagée, il faut créer un fichier mappé en utilisant la fonction

HANDLE CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);

Paramètres:

hFile Il est possible d'indiquer le handle d'un fichier. Dans ce cas, le fichier mappé sera ce fichier. Si la valeur passé est INVALID_HANDLE_VALUE, c'est le système qui gérera le fichier mappé suivant les valeurs passées dans dwMaximumSizeHigh et dwMaximumSizeLow.

lpAttributes pointeur sur une structure SECURITY_ATTRIBUTES, si vous passez lz valeur NULL, alors il utilise le descripteur de sécurité par défaut. De plus, les processus fils ne pourront pas hériter du handle.

flProtect On indiquera le type de protection pour l'accès au fichier mappé.

Valeur Désignation
PAGE_READONLY Lecture seule. Si vous avez passé un handle de fichier, il doit êtr eouvert avec l'option GENERIC_READ
PAGE_READWRITE Droit en lecture et écriture. Si vous avez passé un handle de fichier, il doit êtr eouvert avec l'option GENERIC_READ et GENERIC_WRITE
PAGE_EXECUTE_READ Lecture et exécution. Si vous avez passé un handle de fichier, il doit êtr eouvert avec l'option GENERIC_READ et GENERIC_EXECUTE
PAGE_EXECUTE_READWRITE ...
PAGE_WRITECOPY il doit être ouvert avec l'option GENERIC_READ. Permet une duplication en mémoire du fichier mappé. S'il n'y a pas d'accès dans cette mémoire par la suite, le fihcier n'est pas affecté


dwMaximumSizeHigh Partie haute de la taille maxi du fichier
dwMaximumSizeLow Partie basse de la taille maxi du fichier

Si vous y passez 0, alors lataille maximum du fichier sera egale à la taille du fichier dont le handle est passé.

Sinon, le code erreur ERROR_FILE_INVALID sera retourné.

lpName Utilisez pour identifier le fichier mappé par le nom (doit se terminé avec 0). N'est pas obligatoire et devra être NULL si non renseigné.
Si le nom est déjà utilisé, alors le système va accéder au fichier mappé et récupérer ses paramètres. S'il s'agit d'un évènement, mutex, sémaphore, waitable timer, ..., la fonction retournera ERROR_INVALID_HANDLE.

En sortie,

Handle du fichier mappé. GetLastError sera à ERROR_ALREADY_EXISTS si le fichier mappé existait déjà.

Si la valeur est NULL, il y a une erreur...

Si le fichier mappé est plus petit en taille que ce qui est demandé, le système va essayer de l'augmenter. Si erreur, il retourenra ERROR_DISK_FULL.

Remarque, initialement, la mémoire ne contient que des 0.

 

MapViewOfFile

Cette fonction permet de charger dans l'espace de mémoire du processus une partie ou la totalité du contenu du fichier mappé.

LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);

Paramètres

hFileMappingObject Handle du fichier mappé récupéré suite à CreateFileMapping ou OpenFileMapping
dwDesiredAccess Type d'accès au fichier mappé

Value Meaning

Valeurs Désignation
FILE_MAP_WRITE Accès en lecture/écriture (fichier mappé devra avec PAGE_READWRITE sélectionné)
FILE_MAP_READ Accès en lecture (fichier mappé avec PAGE_READWRITE ou PAGE_READONLY)
FILE_MAP_COPY On ne demande qu'une copie du fichier mappé. Il ne sera donc pas utilisé vers le fichier mappé sauf s'il y a une demande de maj. Dans ce cas, le système récupère le contenu du fichier mappé, vers la mémoire du processus. La maj est ainsi faite et la protection passe à PAGE_READWRITE.
FILE_MAP_EXECUTE Va de paire avec PAGE_EXECUTE_READ ou PAGE_EXECUTE_READWRITE
   


dwFileOffsetHigh Partie haute de la région de la mémoire à accéder
dwFileOffsetLow et la partie basse

Image non trouvée !Il faut utiliser la fonction void GetSystemInfo(
LPSYSTEM_INFO lpSystemInfo
);

Avec lpSystemInfo un pointeur sur une structure de type SYSTEM_INFO.

On récupère alors le membre dwAllocationGranularity afin de connaître la granularité de la mémoire. La valeur devra alors être un multiple de cette granularité.
dwNumberOfBytesToMap Nombre d'octets à rapatrier. Si 0, alors se sera la totalité.

En sortie, la fonction retourne une adresse contenant les informations rapatriées ou NULL si erreur

Vous pouvez ensuite travailler sur vos données.

Lorsque vous avez fini sur la région désirée, il faut libérer la partie rapatriée en utilisant la fonction

BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress
);

avec lpBaseAddress qui est l'adresse retournée par MapViewOfFile().

Image non trouvée !L'accès au fichier de mapping ne se termine pas, rien ne vous empêchera donc de refaire un accès à une autre région de la mémoire suite à cette commande.

Pour libérer la mémoire appelez CloseHandle() sur le handle obtenu de la fonction CreateFileMapping ou OpenFileMapping().

Accéder aux données d'un fichier mappé

OpenFileMapping

HANDLE OpenFileMapping(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);

Paramètres:

dwDesiredAccess NULL ou un descripteur de sécurité
bInheritHandle TRUE pour que les processus fils hérite du handle.
lpName Pointeur sur une chaîne terminée par 0 pour accéder au fichier mappé

 

Comment utiliser tout celà ?

Soit deux processus voulant se partager de la mémoire. Le premier transmet des données pour le second.

Voici les différentes étapes à suivre:

Tout d'abord le premier programme doit créer la mémoire partager:

CreateFileMapping()

Puis peut accéder au fichier mappé pour stocker des informations:

MapViewOfFile()

stocke ses informations (Nous pourrons utiliser la fonction CopyMemory () pour transférer des données)

Enfin libère sont mapping

UnMapViewOfFile()

A la fin du programme, ou si vous n'avez plus besoin du fichier de mapping, fermez l'accès avec CloseHandle(hMapFile);

 

Pour le second programme:

Accède au fichier mappé par OpenFileMapping() ou par CreateFileMapping()

Puis peut accéder au fichier mappé pour lire des informations:

MapViewOfFile()

lit les informations

Enfin libère sont mapping

UnMapViewOfFile()

A la fin du programme, ou si vous n'avez plus besoin du fichier de mapping, fermez l'accès avec CloseHandle(hMapFile);

 

Voici un exemple de programme:

La première instance va créer un fichier de mapping et stocker un message.

Les instances suivantes vont lire ce message.

Attention, il faut se créer un projet de type Application console.

Image non trouvée !