Sí, mmap crea un mapeo. Normalmente no lee todo el contenido de lo que hayas mapeado en la memoria. Si desea hacer eso, puede usar la llamada al sistema mlock/mlockall para obligar al kernel a leer en la RAM el contenido de la asignación, si corresponde.
No, sí, tal vez. Depende.
Llamando a mmap
generalmente solo significa que para su aplicación, el contenido del archivo asignado se asigna a su espacio de direcciones como si el archivo fue cargado allí. O, como si el archivo realmente existiera en la memoria, como si fueran uno y el mismo (lo que incluye los cambios que se vuelven a escribir en el disco, suponiendo que tenga acceso de escritura).
Ni mas ni menos. No tiene noción de cargar algo, ni la aplicación sabe lo que esto significa.
Una aplicación realmente no tiene conocimiento de algo como la memoria, aunque el sistema de memoria virtual lo hace parecer así. La memoria que una aplicación puede "ver" (y acceder) puede corresponder o no a la memoria física real y, en principio, puede cambiar en cualquier momento, sin previo aviso y sin una razón obvia (obvia para su aplicación).
Además de experimentar un pequeño retraso debido a una falla en la página, una aplicación (en principio) no es consciente de que tal cosa suceda y tiene poco o ningún control sobre ello.
Las aplicaciones, por lo general, cargarán páginas de archivos mapeados (¡incluido el ejecutable principal!) a pedido, como consecuencia de encontrar una falla. Sin embargo, un sistema operativo generalmente intentará obtener datos de forma especulativa para optimizar el rendimiento.
En la práctica, llamar a mmap
inmediatamente comenzará para precargar (asincrónicamente) páginas desde el comienzo del mapeo, hasta un cierto tamaño especificado por la implementación. Lo que significa que, en principio, para archivos pequeños la respuesta sería "sí", y para archivos más grandes sería "no".
Sin embargo, mmap
no se bloquea para esperar a que se complete la lectura anticipada, lo que significa que no tiene garantía de que alguno de los archivos esté en la RAM inmediatamente después de mmap
devoluciones (no es que usted tenga esa garantía en cualquier momento de todos modos!). En la medida en que la respuesta es "tal vez".
En Linux, la última vez que miré, el tamaño predeterminado de captación previa era de 31 bloques (~127k), pero esto puede haber cambiado, además es un parámetro ajustable. A medida que se tocan las páginas cercanas o al final del área precargada, más páginas se precargan de forma asincrónica.
Si has insinuado MADV_RANDOM
a madvise
, la captación previa es "menos probable que suceda", en Linux esto desactiva completamente la captación previa.
Por otro lado, dando el MADV_SEQUENTIAL
La sugerencia precargará de forma asíncrona "más agresivamente" desde el principio del mapeo (y puede descartar las páginas a las que se accede más rápido). Bajo Linux, "más agresivamente" significa el doble de la cantidad normal.
Dando el MADV_WILLNEED
la sugerencia sugiere (pero no garantiza) que todas las páginas en el rango dado se carguen lo antes posible (ya que está diciendo que va a acceder a ellas). El sistema operativo puede ignorar esto, pero en Linux, se trata más como una orden que como una pista, hasta el límite máximo de RSS del proceso y un límite especificado por la implementación (si no recuerdo mal, la mitad de la cantidad de RAM física ).
Tenga en cuenta que MADV_DONTNEED
podría decirse que está mal implementado en Linux. La sugerencia no se interpreta de la manera especificada por POSIX, es decir, está de acuerdo con que las páginas se descarguen por el momento, sino que quiere descartarlas . Lo que no hace una gran diferencia para las páginas asignadas de solo lectura (aparte de un pequeño retraso, que dijiste que estaría bien), pero seguro que sí importa para todo lo demás
En particular, usando MADV_DONTNEED
pensar que Linux liberará páginas innecesarias después de que el sistema operativo las haya escrito perezosamente en el disco no es así como funcionan las cosas ! Debes sincronizar explícitamente o prepararte para una sorpresa.
Habiendo llamado readahead
en el descriptor de archivo antes de llamar a mmap
(o alternativamente, habiendo leído/escrito el archivo previamente), el contenido del archivo en la práctica de hecho estar en RAM inmediatamente.
Sin embargo, esto es solo un detalle de implementación (sistema de memoria virtual unificado) y está sujeto a la presión de la memoria en el sistema.
Llamando al mlock
-suponiendo que tenga éxito- cargará inmediatamente las páginas solicitadas en la RAM. Bloquea hasta que todas las páginas están físicamente presentes y tiene la garantía de que las páginas permanecerán en la RAM hasta que las desbloquee.
Existe funcionalidad para consultar (
mincore
) si alguna o todas las páginas en un rango particular están realmente presentes en ese momento, y la funcionalidad para indicarle al sistema operativo lo que le gustaría ver que suceda sin garantías concretas (madvise
), y finalmente la funcionalidad para forzar la presencia de un subconjunto limitado de páginas en la memoria (mlock
) para procesos privilegiados. Puede que no, tanto por falta de privilegios como por exceder las cuotas o la cantidad de memoria RAM física presente.
De forma predeterminada, mmap() solo configura el mapeo y los retornos (rápido).
Linux (al menos) tiene la opción MAP_POPULATE (ver 'man mmap') que hace exactamente de lo que trata tu pregunta.