MMAP
Section : Manuel du programmeur Linux (
2)
Mise à jour de la version anglaise : 5 juin 2008
Index
Menu principal
NOM
mmap, munmap - Établir/supprimer une projection en mémoire (map/unmap) des fichiers ou des périphériques
SYNOPSIS
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *addr, size_t length);
DESCRIPTION
mmap()
crée une nouvelle projection dans l'espace d'adressage virtuel
du processus appelant.
L'adresse de départ de la nouvelle projection est indiquée dans
addr.
L'argument
length
indique la longueur de la projection.
Si
addr
est NULL,
le noyau choisit l'adresse à laquelle créer la projection ;
c'est la méthode la plus portable pour créer une nouvelle projection.
Si
addr
n'est pas NULL,
le noyau le considère comme un conseil l'endroit où placer la projection ;
sous Linux,
la projection sera créée à la prochaine plus haute frontière de page.
L'adresse de la nouvelle projection est renvoyée comme résultat de l'appel.
Le contenu d'une projection de fichier
(contrairement à une projection anonyme ;
voir
MAP_ANONYMOUS
plus loin), est initialisé avec
length
octets à partir de la position
offset
dans le fichier (ou autre objet) référencé par le descripteur de fichier
fd.
offset
doit être un multiple de la taille de page telle qu'elle est renvoyée par
sysconf(_SC_PAGE_SIZE).
L'argument
prot
indique la protection mémoire que l'on désire pour cette projection,
et ne doit pas entrer en conflit avec le mode d'ouverture du fichier.
Il s'agit soit de
PROT_NONE
(le contenu de la mémoire est inaccessible) soit d'un OU binaire entre
les constantes suivantes :
- PROT_EXEC
-
On peut exécuter du code dans la zone mémoire.
- PROT_READ
-
On peut lire le contenu de la zone mémoire.
- PROT_WRITE
-
On peut écrire dans la zone mémoire.
- PROT_NONE
-
Les pages ne peuvent pas être accédées.
Le paramètre
flags
détermine si les modifications de la projection sont visibles par les autres
processus projetant la même région et si les modifications sont appliquées
au fichier sous-jacent.
Ce comportement est déterminé en incluant exactement
une des valeurs suivantes dans
flags :
- MAP_SHARED
-
Partager cette projection.
Les modifications de la projection sont visibles par les autres processus
qui projettent ce fichier, et sont appliquées au fichier sous-jacent.
En revanche, ce dernier n'est pas nécessairement mis à jour
tant qu'on n'a pas appelé
msync(2)
ou
munmap().
- MAP_PRIVATE
-
Créer une projection privée, utilisant la méthode de copie à l'écriture.
Les modifications de la projection ne sont pas visibles par les autres
processus projetant le même fichier et ne sont pas appliquées au fichier
sous-jacent.
Il n'est pas précisé
si les changements effectués dans le fichier après l'appel
mmap()
seront visibles.
Ces attributs sont décrits dans POSIX.1-2001.
De plus, zéro ou plus des valeurs suivantes peuvent être ajoutées dans
flags
avec un OU binaire :
- MAP_32BIT
-
Faire la projection dans les premiers 2 Go
de l'espace d'adressage du processus.
Ignoré si
MAP_FIXED
est présent.
Cet attribut n'est supporté que sur x86-64, pour les programmes 64 bits.
- MAP_ANON
-
Synonyme de
MAP_ANONYMOUS.
Déconseillé.
- MAP_ANONYMOUS
-
La projection n'est supportée par aucun fichier.
Son contenu est initialisé à zéro.
Les arguments
fd
et
offset
sont ignorés.
Toutefois, certaines implémentations demandent que
fd
vaille
-1 si
MAP_ANONYMOUS
(ou
MAP_ANON)
est utilisé et les applications portables doivent donc s'en assurer.
L'utilisation de
MAP_ANONYMOUS
en conjonction de
MAP_SHARED,
n'est implémenté sous Linux que depuis le noyau 2.4.
- MAP_DENYWRITE
-
Cet attribut est ignoré.
(Autrefois, une tentative d'écriture dans le fichier sous-jacent échouait
avec l'erreur
ETXTBUSY.
Mais ceci permettait des attaques par déni de service.)
- MAP_EXECUTABLE
-
Cet attribut est ignoré.
- MAP_FILE
-
Attribut pour compatibilité. Ignoré.
- MAP_FIXED
-
Ne pas interpréter
addr
comme une indication : placer la projection exactement à cette adresse.
addr
doit être un multiple de la taille de page.
Si la zone mémoire indiquée par
addr
et
len
recouvre des pages d'une projection existante, les parties recouvertes
de la projection existantes seront ignorées.
Si l'adresse indiquée ne peut être utilisée,
mmap()
échouera.
Parce que requérir une adresse fixe pour une projection est moins portable,
il est déconseillé d'utiliser cette option.
- MAP_GROWSDOWN
-
Utilisé pour les piles.
Indique au système de gestion de la mémoire virtuelle
que la projection doit s'étendre en croissant vers le bas de la mémoire.
- MAP_LOCKED (depuis Linux 2.5.37)
-
Verrouille la page projetée en mémoire à la manière de
mlock(2).
Cet attribut est ignoré sur les noyaux plus anciens.
- MAP_NONBLOCK (depuis Linux 2.5.46)
-
N'a de sens qu'en conjonction avec
MAP_POPULATE.
Ne pas effectuer de lecture anticipée :
créer seulement les entrées de tables de page pour les pages
déjà présentes en RAM.
Depuis Linux 2.6.23, cet attribut rend
MAP_POPULATE
inactif.
Un jour, la combination de
MAP_POPULATE
et
MAP_NONBLOCK
pourrait être réimplémentées.
- MAP_NORESERVE
-
Ne pas réserver d'espace de swap pour les pages de cette projection.
Une telle réservation garantit que l'on puisse modifier la projection.
Sans réservation, on peut recevoir un signal
SIGSEGV
durant une écriture,
s'il n'y a plus de mémoire physique disponible.
Voir également la discussion sur le fichier
/proc/sys/vm/overcommit_memory
dans
proc(5).
Dans les noyaux antérieurs le 2.6, cet attribut n'avait d'effet que pour
les projections privées.
- MAP_POPULATE (depuis Linux 2.5.46)
-
Remplit les tables de pages pour une projection de fichier.
Pour une projection de fichier, cela provoque
une lecture anticipée sur le fichier.
Les accès ultérieurs à la projection ne seront pas bloqués
par des fautes de pages.
MAP_POPULATE
n'est pris en charge que pour les projections privées depuis Linux 2.6.23.
Parmi les attributs précédents, seul
MAP_FIXED
est spécifié dans POSIX.1-2001.
Toutefois, la plupart des systèmes prennent également en charge
MAP_ANONYMOUS
(ou son synonyme
MAP_ANON).
Certains systèmes utilisent les attributs supplémentaires
MAP_AUTOGROW,
MAP_AUTORESRV,
MAP_COPY
et
MAP_LOCAL.
La mémoire obtenue par
mmap()
est préservée lors d'un
fork(2),
avec les mêmes attributs.
La projection doit avoir une taille multiple de celle des pages.
Pour un fichier dont la longueur n'est pas un multiple de la taille
de page, la mémoire restante est remplie de zéros lors de la projection,
et les écritures dans cette zone n'affectent pas le fichier.
Les effets de la modification de la taille du fichier sous-jacent sur
les pages correspondant aux zones ajoutées ou supprimées
ne sont pas précisés.
munmap()
L'appel système
munmap()
détruit la projection dans la zone de mémoire spécifiée,
et s'arrange pour que toute référence ultérieure à cette zone mémoire
déclenche une erreur d'adressage.
La projection est aussi automatiquement détruite
lorsque le processus se termine.
À l'inverse, la fermeture du descripteur de fichier
ne supprime pas la projection.
L'adresse
addr
doit être un multiple de la taille de page.
Toutes les pages contenant une partie de l'intervalle indiqué sont libérées,
et tout accès ultérieur déclenchera
SIGSEGV.
Aucune erreur n'est détectée si l'intervalle indiqué ne contient pas
de page projetée.
Modifications d'horodatage pour les projections supportées par un fichier
Pour les projections supportées par un fichier, le champ
st_atime
du fichier peut être mis à jour à tout moment entre l'appel
mmap()
et le
munmap()
correspondant.
Le premier accès dans la page projetée
mettra le champ à jour si cela n'a pas été déjà fait.
Les champs
st_ctime
et
st_mtime
pour un fichier projeté avec
PROT_WRITE
et
MAP_SHARED
seront mis à jour après
une écriture dans la région projetée, et avant l'éventuel
msync(2)
suivant avec attribut
MS_SYNC
ou
MS_ASYNC.
VALEUR RENVOYÉE
mmap()
renvoie un pointeur sur la zone de mémoire, s'il réussit.
En cas d'échec il retourne la valeur
MAP_FAILED
(c'est-à-dire
(void *) -1)
et
errno
contient le code d'erreur.
munmap()
renvoie 0 s'il réussit.
En cas d'échec, -1 est renvoyé et
errno
contient le code d'erreur (probablement
EINVAL).
ERREURS
- EACCES
-
Le descripteur ne correspond pas à un fichier normal, ou
on demande une projection privée
MAP_PRIVATE
mais
fd
n'est pas ouvert en lecture, ou on demande une projection partagée
MAP_SHARED
avec protection
PROT_WRITE,
mais
fd
n'est pas ouvert en lecture et écriture
(O_RDWR).
Ou encore
PROT_WRITE
est demandé, mais le fichier est ouvert en ajout seulement.
- EAGAIN
-
Le fichier est verrouillé,
ou trop de pages ont été verrouillées en mémoire (voir
setrlimit(2)).
- EBADF
-
fd
n'est pas un descripteur de fichier valide (et
MAP_ANONYMOUS
n'était pas précisé).
- EINVAL
-
addr,
length
ou
offset
sont invalides.
(Par exemple : zone trop grande,
ou non alignée sur une frontière de page).
- EINVAL
-
(Depuis Linux 2.6.12),
length
valait 0.
- EINVAL
-
flags
ne contient ni
MAP_PRIVATE,
ni
MAP_SHARED,
soit les contient tous les deux.
- ENFILE
-
La limite du nombre total de fichiers ouverts
sur le système a été atteinte.
- ENODEV
-
Le système de fichiers sous-jacent ne supporte pas
la projection en mémoire.
- ENOMEM
-
Pas assez de mémoire, ou le nombre maximal de projection par processus
a été dépassé.
- EPERM
-
L'argument
prot
a demandé
PROT_EXEC
mais la zone appartient à un fichier sur un système de fichiers monté
sans permission d'exécution.
- ETXTBSY
-
MAP_DENYWRITE
a été réclamé mais
fd
est ouvert en écriture.
L'accès à une zone de projection peut déclencher les signaux suivants :
- SIGSEGV
-
Tentative d'écriture dans une zone en lecture seule.
- SIGBUS
-
Tentative d'accès à une portion de la zone qui ne correspond pas
au fichier (par exemple après la fin du fichier,
y compris lorsqu'un autre processus l'a tronqué).
CONFORMITÉ
SVr4, BSD 4.4, POSIX.1-2001.
DISPONIBILITÉ
Sur les systèmes POSIX sur lesquels
mmap(),
msync(2)
et
munmap()
sont disponibles, la constante symbolique
_POSIX_MAPPED_FILES
est définie dans
<unistd.h>
comme étant une valeur supérieure à 0.
(Voir aussi
sysconf(3).)
NOTES
Depuis le noyau 2.4, cet appel système a été remplacé par
mmap2(2).
Aujourd'hui,
la fonction enveloppe
mmap()
de la glibc invoque
mmap2(2)
avec une valeur
offset
convenablement ajustée.
Sur certaines architectures matérielles (par exemple, i386),
PROT_WRITE
implique
PROT_READ.
Cela dépend de l'architecture si
PROT_READ
implique
PROT_EXEC
ou non.
Les programmes portables doivent toujours indiquer
PROT_EXEC
s'ils veulent exécuter du code dans la projection.
La manière portable de créer une projection est de spécifier
addr
à 0 (NULL), et d'omettre
MAP_FIXED
dans
flags.
Dans ce cas, le système choisit l'adresse de la projection ;
l'adresse est choisie de manière à ne pas entrer en conflit avec une
projection existante et de ne pas être nulle.
Si l'attribut
MAP_FIXED
est indiqué et si
addr
est 0 (NULL), l'adresse projetée sera zéro (NULL).
BOGUES
Sous Linux, il n'y a aucune garantie comme celle suggérée sous
MAP_NORESERVE.
Par défaut, tout processus peut être tué à tout moment
lorsque le système n'a plus de mémoire mémoire.
Dans les noyaux antérieurs à 2.6.7, l'attribut
MAP_POPULATE
n'avait d'effet que si
prot
avait la valeur
PROT_NONE.
SUSv3 indique que
mmap()
devrait échouer si
length
vaut 0.
Toutefois, dans les noyaux antérieurs à 2.6.12,
mmap()
réussissait dans ce cas : aucun projection n'était créée et l'appel renvoyait
addr.
Depuis le noyau 2.6.12,
mmap()
échoue avec l'erreur
EINVAL
dans ce cas.
EXEMPLE
Le programme suivant affiche sur la sortie standard une partie du fichier
fourni en tant que premier argument de la ligne de commande.
La plage d'octets à afficher est indiquée par les valeurs d'offset et de
longueur fournies comme deuxième et troisième arguments de la ligne
de commande.
Le programme crée une projection mémoire des pages du fichier nécessaires
et utilise
write(2)
pour écrire les octets souhaités.
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
char *addr;
int fd;
struct stat sb;
off_t offset, pa_offset;
size_t length;
ssize_t s;
if (argc < 3 || argc > 4) {
fprintf(stderr, "%s fichier offset [longueur]\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
handle_error("open");
if (fstat(fd, &sb) == -1) /* Pour obtenir la taille du fichier */
handle_error("fstat");
offset = atoi(argv[2]);
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
/* l'offset pour mmap() doit être aligné sur une page */
if (offset >= sb.st_size) {
fprintf(stderr, "L'offset dépasse la fin du fichier\n");
exit(EXIT_FAILURE);
}
if (argc == 4) {
length = atoi(argv[3]);
if (offset + length > sb.st_size)
length = sb.st_size - offset;
/* Impossible d'afficher les octets en dehors du fichier */
} else { /* Pas de paramètre longueur ==> affichage jusqu'à la fin du fichier */
length = sb.st_size - offset;
}
addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
MAP_PRIVATE, fd, pa_offset);
if (addr == MAP_FAILED)
handle_error("mmap");
s = write(STDOUT_FILENO, addr + offset - pa_offset, length);
if (s != length) {
if (s == -1)
handle_error("write");
fprintf(stderr, "écriture partielle");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
} /* main */
VOIR AUSSI
getpagesize(2),
mincore(2),
mlock(2),
mmap2(2),
mprotect(2),
mremap(2),
msync(2),
remap_file_pages(2),
setrlimit(2),
shmat(2),
shm_open(3),
shm_overview(7)
B.O. Gallmeister, POSIX.4, O'Reilly, pp. 128-129 et 389-391.
TRADUCTION
Ce document est une traduction réalisée par Christophe Blaess
<http://www.blaess.fr/christophe/> le 14 octobre 1996
et révisée le 4 juillet 2008.
L'équipe de traduction a fait le maximum pour réaliser une adaptation
française de qualité. La version anglaise la plus à jour de ce document est
toujours consultable via la commande : « LANG=C man 2 mmap ».
N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute
erreur dans cette page de manuel.
Index
- NOM
-
- SYNOPSIS
-
- DESCRIPTION
-
- munmap()
-
- Modifications d'horodatage pour les projections supportées par un fichier
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- CONFORMITÉ
-
- DISPONIBILITÉ
-
- NOTES
-
- BOGUES
-
- EXEMPLE
-
- VOIR AUSSI
-
- TRADUCTION
-
Dernière mise à jour : 4 juillet 2008