mmap

MMAP(2)                   Manuel du programmeur Linux                  MMAP(2)



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);

       Consultez la section NOTES pour plus d'informations sur les exigences
       de la macro de test de fonctionnalité.

DESCRIPTION
       mmap() crée une nouvelle projection dans l'espace d'adressage virtuel
       du processus appelant. L'adresse de démarrage de la nouvelle
       projection est indiquée dans addr. Le paramètre length indique la
       longueur de la projection.

       Si addr est NULL, le noyau choisit l'adresse à laquelle démarrer 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 une indication sur l'endroit où placer la projection ; sous
       Linux, elle sera placée à une frontière de page proche. L'adresse de
       la nouvelle projection est renvoyée comme résultat de l'appel.

       Le contenu d'une projection de fichier (par opposition à une
       projection anonyme ; voir ci-dessous MAP_ANONYMOUS) est initialisé
       avec length octets à partir de la position offset dans le fichier (ou
       autre objet) correspondant au descripteur de fichier fd. offset doit
       être un multiple de la taille de page, renvoyée par
       sysconf(_SC_PAGE_SIZE).

       L'argument prot indique la protection que l'on désire pour cette zone
       de mémoire, 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 depuis 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 la projection. Les modifications de la projection
                  sont visibles dans 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 depuis les autres processus projetant le
                  même fichier, et ne modifient pas le fichier lui-même. Il
                  n'est pas précisé si les changements effectués dans le
                  fichier après l'appel mmap() seront visibles.

       Ces deux attributs sont décrits dans POSIX.1-2001.

       De plus, zéro ou plus des valeurs suivantes peuvent être incluses
       dans flags (avec un OU binaire) :

       MAP_32BIT (depuis Linux 2.4.20, 2.6)
              Placer la projection dans les deux premiers gigaoctets de
              l'espace d'adressage du processus. Cet attribut n'est pris en
              charge que sous x86-64, pour les programmes 64 bits. Il a été
              ajouté pour permettre à la pile d'un thread d'être allouée
              dans les deux premiers gigaoctets de mémoire, afin d'améliorer
              les performances des changements de contexte sur les premiers
              processeurs 64 bits. Les processeurs x86-64 modernes n'ont plus
              ces problèmes de performance, donc l'utilisation de cet
              attribut n'est pas nécessaire sur ces systèmes. L'attribut
              MAP_32BIT est ignoré quand MAP_FIXED est positionné.

       MAP_ANON
              Synonyme de MAP_ANONYMOUS. Déconseillé.

       MAP_ANONYMOUS
              La projection n'est supportée par aucun fichier ; son contenu
              est initialisé à 0. Les arguments fd et offset sont ignorés ;
              cependant, certaines implémentations demandent que fd soit -1
              si MAP_ANONYMOUS (ou MAP_ANON) est utilisé, et les applications
              portables doivent donc s'en assurer. Cet attribut, utilisé en
              conjonction de MAP_SHARED, n'est implémenté que depuis Linux
              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 considérer addr comme une indication : n'utiliser que
              l'adresse indiquée. 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, la partie recouverte de la
              projection existante sera ignorée. Si l'adresse indiquée ne
              peut être utilisée, mmap() échouera. Il est déconseillé
              d'utiliser cette option, car requérir une adresse fixe pour une
              projection n'est pas portable.

       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_HUGETLB (depuis Linux 2.6.32)
              Allouer la projection à l'aide de « pages immenses ».
              Consultez le fichier source du noyau Linux
              Documentation/vm/hugetlbpage.txt pour plus d'informations.

       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 fait que MAP_POPULATE n'a
              aucun effet. Un jour la combinaison de MAP_POPULATE et
              MAP_NONBLOCK pourra être implémentée de nouveau.

       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 les zones soumises à une copie-en-écriture. Sans
              réservation, on peut recevoir un signal SIGSEGV durant une
              écriture, s'il n'y a plus de place disponible. Consultez
              également la description du fichier
              /proc/sys/vm/overcommit_memory dans la page proc(5). Dans les
              noyaux antérieurs à 2.6, cet attribut n'avait d'effet que pour
              les projections privées modifiables.

       MAP_POPULATE (depuis Linux 2.5.46)
              Remplit les tables de pages pour une projection. Pour une
              projection de fichier, ceci s'effectue par une lecture
              anticipée du fichier. Les accès ultérieurs à la projection
              ne seront pas bloqués par des fautes de pages. MAP_POPULATE
              n'est géré pour les projections privées que depuis
              Linux 2.6.23.

       MAP_STACK (depuis Linux 2.6.27)
              Alloue la projection à une adresse qui convient pour la pile
              d'un processus ou d'un thread. Cet attribut n'a pour l'instant
              aucun effet, mais est utilisé par l'implémentation des threads
              de la glibc de telle sorte que si certaines architectures
              nécessitent un traitement particulier pour l'allocation de la
              pile, leur prise en charge par la suite par la glibc pourra
              être implémentée de façon transparente.

       MAP_UNINITIALIZED (depuis Linux 2.6.33)
              N'efface pas les pages anonymes. Cet attribut n'a pour l'instant
              un effet que si le noyau a été configuré avec l'option
              CONFIG_MMAP_ALLOW_UNINITIALIZED. Ã cause des implications sur la
              sécurité, cette option n'est normalement active que sur des
              périphériques embarqués (c'est-à -dire avec des
              périphériques avec lesquels il est possible d'avoir un
              contrôle total de la mémoire utilisateur).

       Parmi les attributs ci-dessus, seul MAP_FIXED est spécifié dans
       POSIX.1-2001. Cependant, la plupart des systèmes gèrent aussi
       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 au travers 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.‐à ‐d. (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 de fichier 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 (consultez setrlimit(2)).

       EBADF  fd n'est pas un descripteur de fichier valable (et MAP_ANONYMOUS
              n'était pas précisé).

       EINVAL addr ou 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 est nul.

       EINVAL flags ne contient ni MAP_PRIVATE ni MAP_SHARED, ou 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 projections 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.

       EOVERFLOW
              Sur architecture 32 bits avec l'extension de fichiers très
              grands (c'est-Ã -dire utilisant un off_t sur 64 bits) : le
              nombre de pages utilisées pour length plus le nombre de pages
              utilisées pour offset dépasserait unsigned long (32 bits).

       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. (Consultez
       aussi sysconf(3).)

NOTES
       Cette page décrit l'interface fournie par la fonction mmap() de la
       glibc. Initialement, cette fonction appelait un appel système du même
       nom. Depuis le noyau 2.4, cet appel système a été remplacé par
       mmap2(2). De nos jours, la fonction mmap() de la glibc appelle mmap2(2)
       avec la bonne valeur pour offset.

       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 vaut 0
       (NULL), l'adresse projetée sera zéro (NULL).

       Certaines constantes de flags sont définies seulement si _BSD_SOURCE
       ou _SVID_SOURCE est défini.  (La définition de _GNU_SOURCE suffit
       également, et son usage aurait été plus logique, puisque ces
       attributs sont tous spécifiques à Linux.) Les attributs adéquats
       sont :MAP_32BIT, MAP_ANONYMOUS (et son synonyme MAP_ANON),
       MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN, MAP_HUGETLB,
       MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE, et MAP_STACK.

BOGUES
       Sous Linux, il n'y a aucune garantie comme celles indiquées plus haut
       à propos de MAP_NORESERVE. Par défaut, n'importe quel processus peut
       être tué à tout moment lorsque le système n'a plus de mémoire.

       Dans les noyaux antérieurs à 2.6.7, le drapeau MAP_POPULATE n'avait
       d'effet que si prot était PROT_NONE.

       SUSv3 indique que mmap() devrait échouer si length est 0. Cependant,
       avec les versions de Linux antérieures à 2.6.12, mmap() réussissait
       dans ce cas : aucune projection n'était créée, et l'appel renvoyait
       addr. Depuis le noyau 2.6.12, mmap() échoue avec le code d'erreur
       EINVAL si length est nul.

       POSIX spécifie que le système devrait toujours remplir de zéros
       toutes les pages incomplètes à la fin de l'objet et que le système
       n'écrira jamais de modification de l'objet au-delà de sa fin. Sous
       Linux, lors de l'écriture de données vers ce genre de pages
       incomplètes après la fin de l'objet, les données restent dans le
       cache de page même après que le fichier soit fermé et déprojeté,
       et même si les données ne sont jamais écrites vers le fichier
       lui-même, les projections suivantes pourraient voir le contenu
       modifié. Dans certains cas, cela pourrait être corrigé en appelant
       msync(2) avant la déprojection. Cependant, cela ne fonctionne pas sur
       tmpfs (par exemple en utilisant l'interface de mémoire partagée POSIX
       documentée dans shm_overview(7)).

EXEMPLE
       Le programme suivant affiche la partie du fichier, précisé par le
       premier argument de la ligne de commande, sur la sortie standard. Les
       octets qui seront affichés sont précisés à partir d'un offset
       (déplacement) et d'une longueur en deuxième et troisième paramètre.
       Le code fait une projection mémoire des pages nécessaires du fichier
       puis utilise write(2) pour afficher les octets voulus.

   Source du programme
       #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);
       }

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)

       Dans proc(5), les descriptions des fichiers /proc/[pid]/maps,
       /proc/[pid]/map_files, and /proc/[pid]/smaps.

       B.O. Gallmeister, POSIX.4, O'Reilly, pp. 128–129 et 389–391.

COLOPHON
       Cette page fait partie de la publication 3.70 du projet man-pages
       Linux. Une description du projet et des instructions pour signaler des
       anomalies peuvent être trouvées à l'adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION
       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
       <http://po4a.alioth.debian.org/> par l'équipe de traduction
       francophone au sein du projet perkamon
       <http://perkamon.alioth.debian.org/>.

       Thierry Vignaud (2002), Alain Portal
       <http://manpagesfr.free.fr/> (2006).  Julien Cristau et l'équipe
       francophone de traduction de Debian (2006-2009).

       Veuillez signaler toute erreur de traduction en écrivant Ã
       <perkamon-fr@traduc.org>.

       Vous pouvez toujours avoir accès à la version anglaise de ce document
       en utilisant la commande « LC_ALL=C man <section> <page_de_man> ».



Linux                            6 avril 2014                          MMAP(2)