Scroll to navigation

MREMAP(2) Manuel du programmeur Linux MREMAP(2)

NOM

mremap - Modifier une projection de la mémoire virtuelle

SYNOPSIS

#define _GNU_SOURCE         /* Consultez feature_test_macros(7) */
#include <sys/mman.h>
void *mremap(void *old_address, size_t old_size,
             size_t new_size, int flags, ... /* void *new_address */);

DESCRIPTION

mremap() agrandit (ou diminue) une projection (Ndt : mapping) de mémoire virtuelle en mémoire réelle, en la déplaçant éventuellement (sous contrôle de l'argument flags et de la place disponible dans l'espace d'adressage virtuel).

old_address est l'ancienne adresse du bloc de mémoire virtuelle à agrandir (ou à diminuer). Veuillez noter que old_address doit être alignée sur une frontière de page. old_size est l'ancienne taille du bloc de mémoire virtuelle. new_size est la taille désirée pour le nouveau bloc de mémoire. Un cinquième argument, new_address, peut éventuellement être fourni ; voyez la description de MREMAP_FIXED ci-dessous.

Si la valeur de old_size est de zéro et si old_address renvoie à une projection partageable (voir MAP_SHARED de mmap(2)), mremap() créera une nouvelle projection des mêmes pages. new_size sera la taille de la nouvelle projection et l'emplacement de la nouvelle projection peut être indiqué avec new_address ; voir la description de MREMAP_FIXED ci-dessous. Si une nouvelle projection est demandée à l'aide de cette méthode, l'attribut MREMAP_MAYMOVE doit être indiqué également.

Sous Linux, la mémoire est divisée en pages. Un processus utilisateur dispose d'un ou plusieurs segments linéaires de mémoire virtuelle. À chaque segment correspond une ou plusieurs projections dans les pages de mémoire réelle (dans la table des pages). Chaque segment de mémoire virtuelle dispose de ses propres droits d'accès (sa protection), ce qui peut déclencher des fautes de segmentation si la mémoire est utilisée incorrectement (par exemple, en écrivant dans un segment en lecture seule). De même, une tentative d'accès à la mémoire en dehors des segments déclenche une faute de segmentation.

mremap() utilise le schéma de la table des pages de Linux. mremap() modifie la correspondance entre les adresses virtuelles et les pages de mémoire réelle. Ce mécanisme peut être utilisé pour implémenter un realloc(3) très efficace.

L'argument de masquage flags est 0 ou un des drapeaux suivants :

MREMAP_MAYMOVE
Par défaut, s'il n'y a pas suffisamment d'espace pour agrandir une projection à son emplacement actuel, mremap() échoue. Si ce drapeau est utilisé, le noyau est autorisé à déplacer la projection à une autre adresse virtuelle si nécessaire. Si la projection est déplacée, les pointeurs absolus vers l'ancienne projection deviennent caduques (il faut utiliser des décalages par rapport à l'adresse de début de la projection).
MREMAP_FIXED (depuis Linux 2.3.31)
Ce drapeau a un but similaire à MAP_FIXED pour mmap(2). S'il est utilisé, mremap() prend un cinquième argument void *new_address qui contient une adresse alignée sur un début de page vers laquelle la projection doit être déplacée. Toute projection existant précédemment dans la zone entre new_address et new_size est supprimée. Si MREMAP_FIXED est utilisé, MREMAP_MAYMOVE doit l'être aussi.

Si le segment de mémoire indiqué par old_address et old_size est verrouillé (par mlock(2) ou similaire), ce verrou est maintenu quand le segment est modifié et/ou déplacé. Par conséquent, la quantité de mémoire verrouillée par le processus peut changer.

VALEUR RENVOYÉE

mremap() renvoie un pointeur sur la nouvelle zone de mémoire virtuelle s'il réussit. En cas d'échec, la valeur MAP_FAILED (c'est-à-dire (void *) -1) est renvoyée et errno contient le code d'erreur.

ERREURS

EAGAIN
L'appelant a tenté d'agrandir un segment de mémoire verrouillé, mais c'est impossible sans dépasser la limite RLIMIT_MEMLOCK.
EFAULT
Erreur de segmentation (« Segmentation fault »). Une adresse dans l'intervalle entre old_address et old_address+old_size n'est pas une adresse virtuelle valable pour ce processus. On peut également obtenir EFAULT même s'il existe des projections recouvrant la zone complète demandée, mais que ces projections sont de types différents.
EINVAL
Un paramètre non valable a été donné. Parmi les causes possibles :
  • old_address n'était pas aligné sur une page ;
  • une autre valeur que MREMAP_MAYMOVE ou MREMAP_FIXED était indiquée dans flags ;
  • new_size était zéro ;
  • new_size ou new_address n'était pas valable ;
  • la nouvelle plage d'adresses indiquée par new_address et new_size chevauche l'ancienne plage d'adresses indiquée par old_address et old_size ;
  • MREMAP_FIXED était indiqué sans MREMAP_MAYMOVE ;
  • old_size était de zéro et old_address ne renvoie pas à une projection partageable (mais voir BOGUES) ;
  • old_size valait zéro et l'attribut MREMAP_MAYMOVE n'était pas indiqué.
ENOMEM
La zone de mémoire ne peut pas être agrandie à l'emplacement virtuel actuel, et l'option MREMAP_MAYMOVE n'a pas été fournie dans flags. Ou encore, il n'y a plus assez de mémoire (virtuelle) disponible.

CONFORMITÉ

Cet appel système est spécifique à Linux et ne devrait pas être employé dans des programmes destinés à être portables.

NOTES

Avant la version 2.4, la glibc ne fournissait pas la définition de MREMAP_FIXED et le prototype de mremap() ne permettait pas de passer le paramètre new_address.

Si mremap() est utilisé pour déplacer ou étendre une zone verrouillée avec mlock(2) ou équivalent, l'appel mremap() fera le maximum pour remplir la nouvelle zone mais il n'échouera pas avec ENOMEM si la zone ne peut pas être remplie.

BOGUES

Avant Linux 4.14, si old_size valait zéro et si la projection à laquelle renvoyait old_address était une projection privée (MAP_PRIVATE de mmap(2)), mremap() créait une nouvelle projection privée sans lien avec celle d'origine. Ce comportement était intentionnel et probablement non prévu dans des applications de l'espace utilisateur (l'intention de mremap() étant de créer une nouvelle projection à partir de celle d'origine). Depuis Linux 4.14, mremap() échoue avec l'erreur EINVAL dans ce scénario.

VOIR AUSSI

brk(2), getpagesize(2), getrlimit(2), mlock(2), mmap(2), sbrk(2), malloc(3), realloc(3)

Votre manuel favori à propos de systèmes d'exploitation, pour des informations supplémentaires sur la mémoire paginée (par exemple Modern Operating Systems de Andrew S. Tanenbaum, Inside Linux par Randolf Bentson, The Design of the UNIX Operating System par Maurice J. Bach)

COLOPHON

Cette page fait partie de la publication 5.04 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies et la dernière version de cette page peuvent être trouvées à l'adresse https://www.kernel.org/doc/man-pages/.

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.

6 mars 2019 Linux