Oui, mmap crée un mappage. Il ne lit normalement pas tout le contenu de tout ce que vous avez mappé en mémoire. Si vous le souhaitez, vous pouvez utiliser l'appel système mlock/mlockall pour forcer le noyau à lire dans la RAM le contenu du mappage, le cas échéant.
Non, oui, peut-être. Cela dépend.
Appel mmap
généralement signifie seulement que pour votre application, le contenu du fichier mappé est mappé à son espace d'adressage comme si le fichier y a été chargé. Ou, comme si le fichier existait réellement en mémoire, comme s'il s'agissait d'un seul et même fichier (ce qui inclut les modifications réécrites sur le disque, en supposant que vous ayez un accès en écriture).
Ni plus ni moins. Il n'a aucune idée de charger quelque chose, et l'application ne sait pas non plus ce que cela signifie.
Une application n'a pas vraiment connaissance de quelque chose comme la mémoire, bien que le système de mémoire virtuelle la fasse apparaître comme ça. La mémoire qu'une application peut "voir" (et accéder) peut correspondre ou non à la mémoire physique réelle, et celle-ci peut en principe changer à tout moment, sans avertissement préalable, et sans raison apparente (évidente pour votre application).
Hormis éventuellement un léger retard dû à un défaut de page, une application est (en principe) totalement inconsciente de ce qui se passe et n'a que peu ou pas de contrôle dessus.
Les applications chargeront généralement des pages à partir de fichiers mappés (y compris l'exécutable principal !) À la demande, à la suite d'une erreur rencontrée. Cependant, un système d'exploitation essaiera généralement de pré-extraire les données de manière spéculative pour optimiser les performances.
En pratique, appeler le mmap
va immédiatement commencer pour préextraire (de manière asynchrone) les pages depuis le début du mappage, jusqu'à une certaine taille spécifiée par l'implémentation. Ce qui signifie, en principe, que pour les petits fichiers, la réponse serait "oui", et pour les fichiers plus volumineux, ce serait "non".
Cependant, mmap
ne bloque pas l'attente de la fin de la lecture anticipée, ce qui signifie que vous n'avez aucune garantie que l'un des fichiers se trouve dans la RAM immédiatement après mmap
retours (pas que vous ayez cette garantie à tout moment de toute façon !). Dans la mesure où la réponse est "peut-être".
Sous Linux, la dernière fois que j'ai regardé, la taille de prélecture par défaut était de 31 blocs (~ 127k) - mais cela a peut-être changé, en plus c'est un paramètre réglable. Au fur et à mesure que les pages proches ou à la fin de la zone préextraite sont touchées, davantage de pages sont préextraites de manière asynchrone.
Si vous avez suggéré MADV_RANDOM
à madvise
, la prélecture est "moins susceptible de se produire", sous Linux, cela désactive complètement la prélecture.
D'autre part, donner le MADV_SEQUENTIAL
hint effectuera une prélecture asynchrone "plus agressive" en commençant par le début du mappage (et peut supprimer les pages consultées plus rapidement). Sous Linux, "plus agressif" signifie le double de la quantité normale.
Donner le MADV_WILLNEED
hint suggère (mais ne garantit pas) que toutes les pages de la plage donnée soient chargées dès que possible (puisque vous dites que vous allez y accéder). Le système d'exploitation peut ignorer cela, mais sous Linux, il est traité plutôt comme un ordre que comme un indice, jusqu'à la limite RSS maximale du processus et une limite spécifiée par l'implémentation (si je me souviens bien, la moitié de la quantité de RAM physique ).
Notez que MADV_DONTNEED
est sans doute mal implémenté sous Linux. L'indice n'est pas interprété de la manière spécifiée par POSIX, c'est-à-dire que vous êtes d'accord pour que les pages soient paginées pour le moment, mais plutôt que vous voulez les supprimer . Ce qui ne fait pas une grande différence pour les pages mappées en lecture seule (autre qu'un petit délai, ce qui, selon vous, serait OK), mais c'est sûr important pour tout le reste.
En particulier, en utilisant MADV_DONTNEED
penser que Linux publiera des pages inutiles après que le système d'exploitation les aura écrites paresseusement sur le disque n'est pas comme ça que les choses fonctionnent ! Vous devez explicitement synchroniser ou vous préparer à une surprise.
Après avoir appelé readahead
sur le descripteur de fichier avant d'appeler le mmap
(ou alternativement, après avoir lu/écrit le fichier précédemment), le contenu du fichier sera en pratique en effet être dans la RAM immédiatement.
Il ne s'agit cependant que d'un détail d'implémentation (système de mémoire virtuelle unifiée), et sujet à une pression mémoire sur le système.
Appel mlock
chargera immédiatement - en supposant que cela réussisse - les pages demandées dans la RAM. Il bloque jusqu'à ce que toutes les pages soient physiquement présentes, et vous avez la garantie que les pages resteront dans la RAM jusqu'à ce que vous les déverrouilliez.
Il existe une fonctionnalité pour interroger (
mincore
) si une ou toutes les pages d'une plage particulière sont réellement présentes au moment même, et une fonctionnalité pour indiquer au système d'exploitation ce que vous souhaitez voir se produire sans aucune garantie absolue (madvise
), et enfin une fonctionnalité pour forcer un sous-ensemble limité de pages à être présent en mémoire (mlock
) pour les processus privilégiés. Ce n'est peut-être pas le cas, à la fois par manque de privilèges et par dépassement des quotas ou de la quantité de RAM physique présente.
Par défaut, mmap() ne configure que le mapping et retourne (rapidement).
Linux (au moins) a l'option MAP_POPULATE (voir 'man mmap') qui fait exactement le sujet de votre question.