mremap(2) System Calls Manual mremap(2) NOM mremap - Modifier une projection de la memoire virtuelle BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #define _GNU_SOURCE /* Consultez feature_test_macros(7) */ #include void *mremap(void old_address[.old_size], size_t old_size, size_t new_size, int flags, ... /* void *new_address */); DESCRIPTION mremap() agrandit (ou diminue) une projection (Ndt : mapping) de memoire virtuelle en memoire reelle, en la deplacant eventuellement (sous controle de l'argument flags et de la place disponible dans l'espace d'adressage virtuel). old_address est l'ancienne adresse du bloc de memoire virtuelle a agrandir (ou a diminuer). Veuillez noter que old_address doit etre alignee sur une frontiere de page. old_size est l'ancienne taille du bloc de memoire virtuelle. new_size est la taille desiree pour le nouveau bloc de memoire. Un cinquieme argument, new_address, peut eventuellement etre fourni ; voyez la description de MREMAP_FIXED ci-dessous. Si la valeur de old_size est de zero et si old_address renvoie a une projection partageable (voir la description de MAP_SHARED dans mmap(2)), mremap() creera une nouvelle projection des memes pages. new_size sera la taille de la nouvelle projection et l'emplacement de la nouvelle projection peut etre indique avec new_address ; voir la description de MREMAP_FIXED ci-dessous. Si une nouvelle projection est demandee a l'aide de cette methode, l'attribut MREMAP_MAYMOVE doit etre indique egalement. L'argument de masquage flags est soit 0, soit un des attributs suivants : MREMAP_MAYMOVE Par defaut, s'il n'y a pas suffisamment d'espace pour agrandir une projection a son emplacement actuel, mremap() echoue. Si ce drapeau est utilise, le noyau est autorise a deplacer la projection a une autre adresse virtuelle si necessaire. Si la projection est deplacee, les pointeurs absolus vers l'ancienne projection deviennent caduques (il faut utiliser des decalages par rapport a l'adresse de debut de la projection). MREMAP_FIXED (depuis Linux 2.3.31) Ce drapeau a un but similaire a MAP_FIXED pour mmap(2). S'il est utilise, mremap() prend un cinquieme argument void *new_address qui contient une adresse alignee sur un debut de page vers laquelle la projection doit etre deplacee. Toute projection existant precedemment dans la zone entre new_address et new_size est supprimee. Si MREMAP_FIXED est indique, MREMAP_MAYMOVE doit egalement etre indique. MREMAP_DONTUNMAP (depuis Linux 5.7) Cet attribut, qui doit etre utilise avec MREMAP_MAYMOVE, refait une projection vers une nouvelle adresse mais il ne supprime pas celle a old_address. L'attribut MREMAP_DONTUNMAP ne peut etre utilise qu'avec des projections privees anonymes (voir la description de MAP_PRIVATE et de MAP_ANONYMOUS dans mmap(2)). A la fin, tous les acces a la plage indiquee par old_address et old_size donneront une erreur de pagination. Elle sera geree par un gestionnaire userfaultfd(2) si l'adresse se situe dans une plage precedemment enregistree avec userfaultfd(2). Sinon, le noyau alloue une page remplie de zeros pour gerer cette erreur. L'attribut MREMAP_DONTUNMAP peut etre utilise pour deplacer de maniere atomique une projection tout en laissant la source associee. Voir les NOTES pour des applications possibles de MREMAP_DONTUNMAP. Si le segment de memoire indique par old_address et old_size est verrouille (par mlock(2) ou similaire), ce verrou est maintenu quand le segment est modifie et/ou deplace. Par consequent, la quantite de memoire verrouillee par le processus peut changer. VALEUR RENVOYEE mremap() renvoie un pointeur sur la nouvelle zone de memoire virtuelle s'il reussit. En cas d'echec, la valeur MAP_FAILED (c'est-a-dire (void *) -1) est renvoyee et errno est defini pour indiquer l'erreur. ERREURS EAGAIN L'appelant a tente d'agrandir un segment de memoire verrouille, mais c'est impossible sans depasser la limite RLIMIT_MEMLOCK. EFAULT 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 egalement obtenir EFAULT meme s'il existe des projections recouvrant la zone complete demandee, mais que ces projections sont de types differents. EINVAL Un parametre non valable a ete donne. Parmi les causes possibles : - old_address n'etait pas aligne sur une page ; - une autre valeur que MREMAP_MAYMOVE, MREMAP_FIXED ou MREMAP_DONTUNMAP a ete indiquee dans flags ; - new_size etait zero ; - new_size ou new_address n'etait pas valable ; - la nouvelle plage d'adresses indiquee par new_address et new_size chevauche l'ancienne plage d'adresses indiquee par old_address et old_size ; - MREMAP_FIXED ou MREMAP_DONTUNMAP etait indique sans MREMAP_MAYMOVE ; - MREMAP_DONTUNMAP etait indique mais une ou plusieurs pages de la plage indiquee par old_address et old_size n'etaient pas privees et anonymes ; - MREMAP_DONTUNMAP etait indique et old_size n'etait pas egal a new_size ; - old_size etait de zero et old_address ne renvoie pas a une projection partageable (mais voir BOGUES) ; - old_size valait zero et l'attribut MREMAP_MAYMOVE n'etait pas indique. ENOMEM Pas assez de memoire disponible pour terminer l'operation. Les causes possibles sont : - La zone de memoire ne peut pas etre agrandie a l'emplacement virtuel actuel, et l'option MREMAP_MAYMOVE n'a pas ete fournie dans flags. Ou encore, il n'y a plus assez de memoire (virtuelle) disponible. - MREMAP_DONTUNMAP a ete utilise, provoquant la creation d'une nouvelle projection qui depasserait la memoire (virtuelle) disponible. Ou alors elle excederait le nombre maximal de projections autorisees. STANDARDS Linux. HISTORIQUE Avant la glibc 2.4, glibc ne fournissait pas la definition de MREMAP_FIXED et le prototype de mremap() ne permettait pas de passer le parametre new_address. NOTES mremap() modifie la correspondance entre les adresses virtuelles et les pages de memoire. Ce mecanisme peut etre utilise pour implementer un realloc(3) tres efficace. Sous Linux, la memoire est divisee en pages. Un processus utilisateur dispose d'un ou plusieurs segments lineaires de memoire virtuelle. A chaque segment correspond une ou plusieurs projections dans les pages de memoire reelle (dans la table des pages). Chaque segment de memoire virtuelle dispose de ses propres droits d'acces (sa protection), ce qui peut declencher des fautes de segmentation (SIGSEGV) si l'acces a la memoire est mal gere (par exemple, en ecrivant dans un segment en lecture seule). De meme, une tentative d'acces a la memoire en dehors des segments declenche une faute de segmentation. Si mremap() est utilise pour deplacer ou etendre une zone verrouillee avec mlock(2) ou equivalent, l'appel mremap() fera le maximum pour remplir la nouvelle zone mais il n'echouera pas avec ENOMEM si la zone ne peut pas etre remplie. Cas d'utilisation de MREMAP_DONTUNMAP Parmi les applications possibles de MREMAP_DONTUNMAP : - userfaultfd(2) non cooperatif : une application peut retirer une plage d'adresses virtuelles en utilisant MREMAP_DONTUNMAP, puis utiliser un gestionnaire userfaultfd(2) pour gerer les erreurs de pagination qui arrivent ensuite lorsque d'autres threads du processus creent des pages dans la plage retiree. - Recuperateur de memoire : MREMAP_DONTUNMAP peut etre utilise avec userfaultfd(2) pour implementer des algorithmes de ramasse-miettes (garbage collection) (par exemple, dans une machine virtuelle Java). Une telle implementation peut etre moins couteuse (et plus simple) que les techniques de collecte traditionnelles qui impliquent de marquer des pages avec une protection PROT_NONE ainsi que l'utilisation d'un gestionnaire SIGSEGV pour capter les acces a ces pages. BOGUES Avant Linux 4.14, si old_size valait zero et si la projection a laquelle renvoyait old_address etait une projection privee (voir la description de MAP_PRIVATE dans mmap(2)), mremap() creait une nouvelle projection privee sans lien avec celle d'origine. Ce comportement etait intentionnel et probablement non prevu dans des applications de l'espace utilisateur (l'intention de mremap() etant de creer une nouvelle projection a partir de celle d'origine). Depuis Linux 4.14, mremap() echoue avec l'erreur EINVAL dans ce scenario. VOIR AUSSI brk(2), getpagesize(2), getrlimit(2), mlock(2), mmap(2), sbrk(2), malloc(3), realloc(3) Votre manuel favori a propos de systemes d'exploitation, pour des informations supplementaires sur la memoire paginee (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) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot et Jean-Philippe MENGUAL Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 16 janvier 2024 mremap(2)