¿Cuándo debo usar mmap para acceder a archivos?

Resuelto Peter Burns asked hace 15 años • 6 respuestas

Los entornos POSIX proporcionan al menos dos formas de acceder a archivos. Están las llamadas al sistema estándar open(), read(), write()y amigos, pero también existe la opción de usar mmap()para asignar el archivo a la memoria virtual.

¿Cuándo es preferible utilizar uno u otro? ¿Cuáles son sus ventajas individuales que merecen incluir dos interfaces?

Peter Burns avatar Nov 03 '08 14:11 Peter Burns
Aceptado

mmapes genial si tienes múltiples procesos accediendo a datos en modo de solo lectura desde el mismo archivo, lo cual es común en el tipo de sistemas de servidor que escribo. mmappermite que todos esos procesos compartan las mismas páginas de memoria física, ahorrando mucha memoria.

mmapTambién permite que el sistema operativo optimice las operaciones de paginación. Por ejemplo, considere dos programas; programa Aque lee un 1MBarchivo en un búfer creado con mallocy programa B que guarda mmapsel archivo de 1 MB en la memoria. Si el sistema operativo tiene que intercambiar parte de Ala memoria, debe escribir el contenido del búfer para intercambiar antes de poder reutilizar la memoria. En Bel caso de, mmaplas páginas no modificadas se pueden reutilizar inmediatamente porque el sistema operativo sabe cómo restaurarlas desde el archivo existente del que se obtuvieron mmap. (El sistema operativo puede detectar qué páginas no están modificadas marcando inicialmente mmaplas páginas en las que se puede escribir como de solo lectura y detectando fallas de segmentación , similar a la estrategia Copiar en escritura ).

mmapTambién es útil para la comunicación entre procesos . Puede mmapleer/escribir un archivo en los procesos que necesitan comunicarse y luego usar primitivas de sincronización en la mmap'dregión (para esto es la MAP_HASSEMAPHOREbandera).

Un lugar mmapque puede resultar incómodo es si necesita trabajar con archivos muy grandes en una máquina de 32 bits. Esto se debe a que mmaptiene que encontrar un bloque contiguo de direcciones en el espacio de direcciones de su proceso que sea lo suficientemente grande como para caber en todo el rango del archivo que se está asignando. Esto puede convertirse en un problema si su espacio de direcciones se fragmenta, donde puede tener 2 GB de espacio de direcciones libres, pero ningún rango individual puede caber en una asignación de archivos de 1 GB. En este caso, es posible que tenga que asignar el archivo en fragmentos más pequeños de los que le gustaría que quepan.

Otra posible incomodidad al mmapreemplazar la lectura/escritura es que debe comenzar el mapeo en desplazamientos del tamaño de la página. Si solo desea obtener algunos datos en el desplazamiento, Xdeberá arreglar ese desplazamiento para que sea compatible con mmap.

Y finalmente, la lectura/escritura es la única forma de trabajar con algunos tipos de archivos. mmapNo se puede utilizar en cosas como tuberías y ttys .

Don Neufeld avatar Nov 03 '2008 08:11 Don Neufeld

Un área en la que encontré que mmap() no era una ventaja fue al leer archivos pequeños (menos de 16K). La sobrecarga de errores de página para leer el archivo completo era muy alta en comparación con hacer una sola llamada al sistema read(). Esto se debe a que el kernel a veces puede satisfacer una lectura por completo en su intervalo de tiempo, lo que significa que su código no cambia. Con un error de página, parecía más probable que se programara otro programa, lo que hacía que la operación del archivo tuviera una mayor latencia.

Ben Combee avatar Nov 03 '2008 22:11 Ben Combee

mmaptiene la ventaja cuando tienes acceso aleatorio a archivos grandes. Otra ventaja es que puedes acceder a él con operaciones de memoria (memcpy, aritmética de punteros), sin preocuparte por el almacenamiento en búfer. La E/S normal a veces puede resultar bastante difícil cuando se utilizan búferes cuando se tienen estructuras más grandes que el búfer. El código de manejo a menudo es difícil de hacer bien, mmap generalmente es más fácil. Dicho esto, existen ciertas trampas al trabajar con mmap. Como ya se ha mencionado, mmapsu configuración es bastante costosa, por lo que vale la pena utilizarla sólo para un tamaño determinado (que varía de una máquina a otra).

Para accesos puramente secuenciales al archivo, tampoco siempre es la mejor solución, aunque una llamada adecuada madvisepuede mitigar el problema.

Debe tener cuidado con las restricciones de alineación de su arquitectura (SPARC, itanium), con E/S de lectura/escritura los buffers suelen estar correctamente alineados y no se bloquean al eliminar la referencia a un puntero convertido.

También hay que tener cuidado de no acceder fuera del mapa. Puede suceder fácilmente si usa funciones de cadena en su mapa y su archivo no contiene un \0 al final. Funcionará la mayor parte del tiempo cuando el tamaño de su archivo no sea un múltiplo del tamaño de la página, ya que la última página está llena con 0 (el área asignada siempre tiene un tamaño múltiplo del tamaño de su página).

Patrick Schlüter avatar May 24 '2010 08:05 Patrick Schlüter

Además de otras buenas respuestas, una cita de la programación del sistema Linux escrita por el experto de Google, Robert Love:

Ventajas demmap( )

La manipulación de archivos a través de mmap( )tiene varias ventajas sobre las llamadas estándar read( )y write( )del sistema. Entre ellos están:

  • Leer y escribir en un archivo asignado en memoria evita la copia superflua que se produce cuando se utilizan llamadas al sistema read( )o write( ), donde los datos deben copiarse hacia y desde un búfer de espacio de usuario.

  • Aparte de posibles errores de página, leer y escribir en un archivo asignado en memoria no genera ninguna llamada al sistema ni sobrecarga de cambio de contexto. Es tan sencillo como acceder a la memoria.

  • Cuando varios procesos asignan el mismo objeto a la memoria, los datos se comparten entre todos los procesos. Las asignaciones de escritura compartidas y de solo lectura se comparten en su totalidad; Las asignaciones de escritura privadas tienen sus páginas aún no COW (copia en escritura) compartidas.

  • La búsqueda alrededor del mapeo implica manipulaciones triviales del puntero. No es necesaria la lseek( )llamada al sistema.

Por estos motivos, mmap( )es una elección inteligente para muchas aplicaciones.

Desventajas demmap( )

Hay algunos puntos a tener en cuenta al utilizar mmap( ):

  • Las asignaciones de memoria siempre tienen un tamaño de número entero de páginas. Por lo tanto, la diferencia entre el tamaño del archivo de respaldo y un número entero de páginas se "desperdicia" como espacio libre. Para archivos pequeños, es posible que se desperdicie un porcentaje significativo del mapeo. Por ejemplo, con páginas de 4 KB, una asignación de 7 bytes desperdicia 4089 bytes.

  • Las asignaciones de memoria deben caber en el espacio de direcciones del proceso. Con un espacio de direcciones de 32 bits, una gran cantidad de asignaciones de distintos tamaños puede provocar la fragmentación del espacio de direcciones, lo que dificulta encontrar grandes regiones contiguas libres. Este problema, por supuesto, es mucho menos evidente con un espacio de direcciones de 64 bits.

  • Existe una sobrecarga al crear y mantener las asignaciones de memoria y las estructuras de datos asociadas dentro del kernel. Esta sobrecarga generalmente se evita mediante la eliminación de la doble copia mencionada en la sección anterior, particularmente para archivos más grandes y a los que se accede con frecuencia.

Por estas razones, los beneficios de mmap( )se obtienen en mayor medida cuando el archivo mapeado es grande (y por lo tanto, cualquier espacio desperdiciado es un pequeño porcentaje del mapeo total), o cuando el tamaño total del archivo mapeado es divisible uniformemente por el tamaño de la página ( y así no se desperdicia espacio).

Miljen Mikic avatar Sep 27 '2017 07:09 Miljen Mikic