A voir également:
- Informatique
- Le code ascii en informatique - Guide
- Jargon informatique - Télécharger - Bureautique
- Que veut dire url en informatique - Guide
- Souris informatique - Guide
- Bal informatique ✓ - Forum Mail
1 réponse
c du copier coller mias bon !!
La mémoire mappée permet à différents processus de communiquer via un fichier partagé. Bien que vous puissiez concevoir l'utilisation de mémoire mappée comme étant à celle d'un segment de mémoire partagée avec un nom, vous devez être conscient qu'il existe des différences techniques. La mémoire mappée peut être utilisée pour la communication interprocessus ou comme un moyen pratique d'accéder au contenu d'un fichier.
La mémoire mappée crée une correspondance entre un fichier et la mémoire d'un processus. Linux divise le fichier en fragments de la taille d'une page puis les copie dans des pages de mémoire virtuelle afin qu'elles puissent être disponibles au sein de l'espace d'adressage d'un processus. Donc le processus peut lire le contenu du fichier par le biais d'accès mémoire classiques. Cela permet un accès rapide aux fichiers.
Vous pouvez vous représenter la mémoire mappée comme l'allocation d'un tampon contenant la totalité d'un fichier, la lecture du fichier dans le tampon, puis (si le tampon est modifié) l'écriture de celui-ci dans le fichier. Linux gère les opérations de lecture et d'écriture à votre place.
Il existe d'autres utilisations des fichiers de mémoire mappée que la communication interprocessus. Quelques unes d'entre elles sont traitées dans la Section 5.3.5, « Autres utilisations de mmap ».
Mapper un fichier ordinaire
Pour mettre en correspondance un fichier ordinaire avec la mémoire d'un processus, utilisez l'appel mmap (« Memory MAPped », Mémoire mappée, prononcez « em-map »). Le premier argument est l'adresse à laquelle vous désirez que Linux mette le fichier en correspondance au sein de l'espace d'adressage de votre processus; la valeur NULL permet à Linux de choisir une adresse de départ disponible. Le second argument est la longueur de l'espace de correspondance en octets. Le troisième argument définit la protection de l'intervalle d'adresses mis en correspondance. La protection consiste en un ou binaire entre PROT_READ, PROT_WRITE et PROT_EXEC, correspondant aux permissions de lecture, d'écriture et d'exécution, respectivement. Le quatrième argument est un drapeau spécifiant des options supplémentaires. Le cinquième argument est un descripteur de fichier pointant vers le fichier à mettre en correspondance, ouvert en lecture. Le dernier argument est le déplacement, par rapport au début du fichier, à partir duquel commencer la mise en correspondance. Vous pouvez mapper tout ou partie du fichier en mémoire en choisissant le déplacement et la longueur de façon appropriée.
Le drapeau est un ou binaire entre ces contraintes:
MAP_FIXED ? Si vous utilisez ce drapeau, Linux utilise l'adresse que vous demandez pour mapper le fichier plutôt que de la considérer comme une indication. Cette adresse doit être alignée sur une page.
MAP_PRIVATE ? Les écritures en mémoire ne doivent pas être répercutées sur le fichier mis en correspondance, mais sur une copie privée du fichier. Aucun autre processus ne voit ces écritures. Ce mode ne doit pas être utilisé avec MAP_SHARED.
MAP_SHARED ? Les écritures sont immédiatement répercutées sur le fichier mis en correspondance. Utilisez ce mode lorsque vous utilisez la mémoire mappée pour l'IPC. Ce mode ne doit pas être utilisé avec MAP_PRIVATE.
Si l'appel se déroule avec succès, la fonction renvoie un pointeur vers le début de la mémoire. S'il échoue, la fonction renvoie MAP_FAILED.
Programmes exemples
Examinons deux programmes pour illustrer l'utilisation des régions de mémoire mappée pour lire et écrire dans des fichiers. Le premier programme, le Listing !!mmapwrite!!, génère un nombre aléatoire et l'écrit dans un fichier mappé en mémoire. Le second programme, le listing !!mmapread!!, lit le nombre, l'affiche et le remplace par le double de sa valeur. Tous deux prennent en argument de ligne de commande le nom du fichier à mettre en correspondance avec la mémoire.
Listing (mmap-write.c) Écrit un nombre aléatoire dans un fichier mappé
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#define FILE_LENGTH 0x100
/* Renvoie un nombre aléatoire compris dans l'intervalle [low,high]. */
int random_range (unsigned const low, unsigned const high)
{
unsigned const range = high - low + 1;
return low + (int) (((double) range) * rand () / (RAND_MAX + 1.0));
}
int main (int argc, char* const argv[])
{
int fd;
void* file_memory;
/* Initialise le générateur de nombres aléatoires. */
srand (time (NULL));
/* Prépare un fichier suffisamment long pour contenir le nombre. */
fd = open (argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
lseek (fd, FILE_LENGTH+1, SEEK_SET);
write (fd, "", 1);
lseek (fd, 0, SEEK_SET);
/* Met en correspondance le fichier et la mémoire. */
file_memory = mmap (0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0);
close (fd);
/* Ecrit un entier aléatoire dans la zone mise en correspondance. */
sprintf((char*) file_memory, "%d\n", random_range (-100, 100));
/* Libère la mémoire (facultatif car le programme se termine). */
munmap (file_memory, FILE_LENGTH);
return 0;
}
Le programme mmap-write ouvre le fichier, le créant s'il n'existe pas. Le second argument de open indique que le fichier est ouvert en lecture et écriture. Comme nous ne connaissons pas la taille du fichier, nous utilisons lseek pour nous assurer qu'il est suffisamment grand pour stocker un entier puis nous nous replaçons au début du fichier.
Le programme met en correspondance le fichier et la mémoire puis ferme le fichier car il n'est plus utile. Il écrit ensuite un entier aléatoire dans la mémoire mappée, et donc dans le fichier, puis libère la mémoire. L'appel munmap n'est pas nécessaire car Linux supprimerait automatiquement la mise en correspondance à la fin du programme.
Listing (mmap-read.c) Lit un entier depuis un fichier mis en correspondance avec la mémoire et le multiplie par deux
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#define FILE_LENGTH 0x100
int main (int argc, char* const argv[])
{
int fd;
void* file_memory;
int integer;
/* Ouvre le fichier. */
fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR);
/* Met en correspondance le fichier et la mémoire. */
file_memory = mmap (0, FILE_LENGTH, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close (fd);
/* Lit l'entier, l'affiche et le multiplie par deux. */
sscanf (file_memory, "%d", &integer);
printf ("valeur : %d\n", integer);
sprintf ((char*) file_memory, "%d\n", 2 * integer);
/* Libère la mémoire (facultatif car le programme se termine). */
munmap (file_memory, FILE_LENGTH);
return 0;
}
Le programme mmap-read lit le nombre à partir du fichier puis y écrit son double. Tout d'abord, il ouvre le fichier et le met en correspondance en lecture/écriture. Comme nous pouvons supposer que le fichier est suffisamment grand pour stocker un entier non signé, nous n'avons pas besoin d'utiliser lseek, comme dans le programme précédent. Le programme lit la valeur à partir de la mémoire en utilisant sscanf puis formate et écrit le double de la valeur en utilisant sprintf.
Voici un exemple de l'exécution de ces programmes d'exemple. Il utilise le fichier /tmp/integer-file.
% ./mmap-write /tmp/integer-file
% cat /tmp/integer-file
42
% ./mmap-read /tmp/integer-file
valeur : 42
% cat /tmp/integer-file
84
Remarquez que le texte 42 a été écrit dans le fichier sur le disque sans jamais appeler write et à été lu par la suite sans appeler read. Notez que ces programmes de démonstration écrivent et lisent l'entier sous forme de chaîne (en utilisant sprintf et sscanf) dans un but d'exemple uniquement ? il n'y a aucune raison pour que le contenu d'un fichier mis en correspondance avec la mémoire soit au format texte. Vous pouvez lire et écrire de façon binaire dans un fichier mis e
n correspondance avec la mémoire.
La mémoire mappée permet à différents processus de communiquer via un fichier partagé. Bien que vous puissiez concevoir l'utilisation de mémoire mappée comme étant à celle d'un segment de mémoire partagée avec un nom, vous devez être conscient qu'il existe des différences techniques. La mémoire mappée peut être utilisée pour la communication interprocessus ou comme un moyen pratique d'accéder au contenu d'un fichier.
La mémoire mappée crée une correspondance entre un fichier et la mémoire d'un processus. Linux divise le fichier en fragments de la taille d'une page puis les copie dans des pages de mémoire virtuelle afin qu'elles puissent être disponibles au sein de l'espace d'adressage d'un processus. Donc le processus peut lire le contenu du fichier par le biais d'accès mémoire classiques. Cela permet un accès rapide aux fichiers.
Vous pouvez vous représenter la mémoire mappée comme l'allocation d'un tampon contenant la totalité d'un fichier, la lecture du fichier dans le tampon, puis (si le tampon est modifié) l'écriture de celui-ci dans le fichier. Linux gère les opérations de lecture et d'écriture à votre place.
Il existe d'autres utilisations des fichiers de mémoire mappée que la communication interprocessus. Quelques unes d'entre elles sont traitées dans la Section 5.3.5, « Autres utilisations de mmap ».
Mapper un fichier ordinaire
Pour mettre en correspondance un fichier ordinaire avec la mémoire d'un processus, utilisez l'appel mmap (« Memory MAPped », Mémoire mappée, prononcez « em-map »). Le premier argument est l'adresse à laquelle vous désirez que Linux mette le fichier en correspondance au sein de l'espace d'adressage de votre processus; la valeur NULL permet à Linux de choisir une adresse de départ disponible. Le second argument est la longueur de l'espace de correspondance en octets. Le troisième argument définit la protection de l'intervalle d'adresses mis en correspondance. La protection consiste en un ou binaire entre PROT_READ, PROT_WRITE et PROT_EXEC, correspondant aux permissions de lecture, d'écriture et d'exécution, respectivement. Le quatrième argument est un drapeau spécifiant des options supplémentaires. Le cinquième argument est un descripteur de fichier pointant vers le fichier à mettre en correspondance, ouvert en lecture. Le dernier argument est le déplacement, par rapport au début du fichier, à partir duquel commencer la mise en correspondance. Vous pouvez mapper tout ou partie du fichier en mémoire en choisissant le déplacement et la longueur de façon appropriée.
Le drapeau est un ou binaire entre ces contraintes:
MAP_FIXED ? Si vous utilisez ce drapeau, Linux utilise l'adresse que vous demandez pour mapper le fichier plutôt que de la considérer comme une indication. Cette adresse doit être alignée sur une page.
MAP_PRIVATE ? Les écritures en mémoire ne doivent pas être répercutées sur le fichier mis en correspondance, mais sur une copie privée du fichier. Aucun autre processus ne voit ces écritures. Ce mode ne doit pas être utilisé avec MAP_SHARED.
MAP_SHARED ? Les écritures sont immédiatement répercutées sur le fichier mis en correspondance. Utilisez ce mode lorsque vous utilisez la mémoire mappée pour l'IPC. Ce mode ne doit pas être utilisé avec MAP_PRIVATE.
Si l'appel se déroule avec succès, la fonction renvoie un pointeur vers le début de la mémoire. S'il échoue, la fonction renvoie MAP_FAILED.
Programmes exemples
Examinons deux programmes pour illustrer l'utilisation des régions de mémoire mappée pour lire et écrire dans des fichiers. Le premier programme, le Listing !!mmapwrite!!, génère un nombre aléatoire et l'écrit dans un fichier mappé en mémoire. Le second programme, le listing !!mmapread!!, lit le nombre, l'affiche et le remplace par le double de sa valeur. Tous deux prennent en argument de ligne de commande le nom du fichier à mettre en correspondance avec la mémoire.
Listing (mmap-write.c) Écrit un nombre aléatoire dans un fichier mappé
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#define FILE_LENGTH 0x100
/* Renvoie un nombre aléatoire compris dans l'intervalle [low,high]. */
int random_range (unsigned const low, unsigned const high)
{
unsigned const range = high - low + 1;
return low + (int) (((double) range) * rand () / (RAND_MAX + 1.0));
}
int main (int argc, char* const argv[])
{
int fd;
void* file_memory;
/* Initialise le générateur de nombres aléatoires. */
srand (time (NULL));
/* Prépare un fichier suffisamment long pour contenir le nombre. */
fd = open (argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
lseek (fd, FILE_LENGTH+1, SEEK_SET);
write (fd, "", 1);
lseek (fd, 0, SEEK_SET);
/* Met en correspondance le fichier et la mémoire. */
file_memory = mmap (0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0);
close (fd);
/* Ecrit un entier aléatoire dans la zone mise en correspondance. */
sprintf((char*) file_memory, "%d\n", random_range (-100, 100));
/* Libère la mémoire (facultatif car le programme se termine). */
munmap (file_memory, FILE_LENGTH);
return 0;
}
Le programme mmap-write ouvre le fichier, le créant s'il n'existe pas. Le second argument de open indique que le fichier est ouvert en lecture et écriture. Comme nous ne connaissons pas la taille du fichier, nous utilisons lseek pour nous assurer qu'il est suffisamment grand pour stocker un entier puis nous nous replaçons au début du fichier.
Le programme met en correspondance le fichier et la mémoire puis ferme le fichier car il n'est plus utile. Il écrit ensuite un entier aléatoire dans la mémoire mappée, et donc dans le fichier, puis libère la mémoire. L'appel munmap n'est pas nécessaire car Linux supprimerait automatiquement la mise en correspondance à la fin du programme.
Listing (mmap-read.c) Lit un entier depuis un fichier mis en correspondance avec la mémoire et le multiplie par deux
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#define FILE_LENGTH 0x100
int main (int argc, char* const argv[])
{
int fd;
void* file_memory;
int integer;
/* Ouvre le fichier. */
fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR);
/* Met en correspondance le fichier et la mémoire. */
file_memory = mmap (0, FILE_LENGTH, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close (fd);
/* Lit l'entier, l'affiche et le multiplie par deux. */
sscanf (file_memory, "%d", &integer);
printf ("valeur : %d\n", integer);
sprintf ((char*) file_memory, "%d\n", 2 * integer);
/* Libère la mémoire (facultatif car le programme se termine). */
munmap (file_memory, FILE_LENGTH);
return 0;
}
Le programme mmap-read lit le nombre à partir du fichier puis y écrit son double. Tout d'abord, il ouvre le fichier et le met en correspondance en lecture/écriture. Comme nous pouvons supposer que le fichier est suffisamment grand pour stocker un entier non signé, nous n'avons pas besoin d'utiliser lseek, comme dans le programme précédent. Le programme lit la valeur à partir de la mémoire en utilisant sscanf puis formate et écrit le double de la valeur en utilisant sprintf.
Voici un exemple de l'exécution de ces programmes d'exemple. Il utilise le fichier /tmp/integer-file.
% ./mmap-write /tmp/integer-file
% cat /tmp/integer-file
42
% ./mmap-read /tmp/integer-file
valeur : 42
% cat /tmp/integer-file
84
Remarquez que le texte 42 a été écrit dans le fichier sur le disque sans jamais appeler write et à été lu par la suite sans appeler read. Notez que ces programmes de démonstration écrivent et lisent l'entier sous forme de chaîne (en utilisant sprintf et sscanf) dans un but d'exemple uniquement ? il n'y a aucune raison pour que le contenu d'un fichier mis en correspondance avec la mémoire soit au format texte. Vous pouvez lire et écrire de façon binaire dans un fichier mis e
n correspondance avec la mémoire.