Pregunta

Los entornos POSIX proporcionan al menos dos formas de acceder a los archivos. Existe el sistema estándar llamado 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 usar uno sobre el otro? ¿Cuáles son sus ventajas individuales que merecen incluir dos interfaces?

¿Fue útil?

Solución

mmap es excelente si tiene múltiples procesos que acceden a los datos de una sola lectura desde el mismo archivo, lo cual es común en el tipo de sistemas de servidor que escribo. mmap permite que todos esos procesos compartan las mismas páginas de memoria física, ahorrando mucha memoria.

mmap también permite que el sistema operativo optimice las operaciones de paginación. Por ejemplo, considere dos programas; el programa A, que lee en un archivo de 1 MB en un búfer que crea con malloc, y el programa B, que coloca el archivo de 1 MB en la memoria. Si el sistema operativo tiene que intercambiar parte de la memoria de A, debe escribir el contenido del búfer para intercambiar antes de poder reutilizar la memoria. En el caso de B, cualquier página mmap'd no modificada puede reutilizarse de inmediato porque el sistema operativo sabe cómo restaurarlas desde el archivo existente desde el que fueron mmap'd. (El sistema operativo puede detectar qué páginas no se modifican marcando inicialmente las páginas de mmaptables que se pueden escribir como de solo lectura y detectando fallas seg, similares a la estrategia Copiar en escritura).

mmap también es útil para la comunicación entre procesos. Puede hacer un mmap de un archivo como lectura / escritura en los procesos que necesitan comunicarse y luego usar primitivas de sincronización en la región mmap'd (para eso es el indicador MAP_HASSEMAPHORE).

Un lugar donde el mmap puede ser incómodo es si necesita trabajar con archivos muy grandes en una máquina de 32 bits. Esto se debe a que mmap tiene que encontrar un bloque de direcciones contiguo en el espacio de direcciones de su proceso que sea lo suficientemente grande como para adaptarse a 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 ajustarse a una asignación de archivos de 1 GB. En este caso, es posible que tenga que asignar el archivo en partes más pequeñas de las que le gustaría que encajen.

Otra incomodidad potencial con mmap como reemplazo de la lectura / escritura es que tiene que comenzar su asignación en las compensaciones del tamaño de la página. Si solo desea obtener algunos datos en la compensación X, deberá corregir esa compensación para que sea compatible con mmap.

Y, por último, leer / escribir es la única manera en que puede trabajar con algunos tipos de archivos. mmap no se puede usar en cosas como tuberías y ttys.

Otros consejos

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

mmap tiene la ventaja de tener acceso aleatorio en archivos grandes. Otra ventaja es que accede a él con operaciones de memoria (memcpy, aritmética de puntero), sin molestarse con el almacenamiento en búfer. La E / S normal a veces puede ser bastante difícil cuando se usan buffers cuando tienes estructuras más grandes que tu buffer. El código a manejar que a menudo es difícil de entender, el mmap es generalmente más fácil. Dicho esto, hay ciertas trampas cuando se trabaja con mmap . Como la gente ya ha mencionado, mmap es bastante costoso de configurar, por lo que vale la pena usarlo solo para un tamaño determinado (que varía de una máquina a otra).

Para accesos puramente secuenciales al archivo, tampoco es siempre la mejor solución, aunque una llamada apropiada a madvise puede mitigar el problema.

Debe tener cuidado con las restricciones de alineación de su arquitectura (SPARC, itanium); con IO de lectura / escritura, los búferes a menudo están alineados correctamente y no quedan atrapados al eliminar la referencia de un puntero fundido.

También debe 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 se rellena con 0 (el área asignada siempre tiene el tamaño de un múltiplo del tamaño de su página).

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

  

Ventajas de mmap ()

     

La manipulación de archivos a través de mmap () tiene varias ventajas sobre el   Llamadas estándar al sistema read () y write () . Entre ellos se encuentran:

     
      
  • Leer y escribir en un archivo mapeado en memoria evita el   copia extraña que se produce al usar el sistema read () o write ()   llamadas, donde los datos se deben copiar hacia y desde un búfer de espacio de usuario.

  •   
  • Aparte de cualquier posible error en la página, leer y escribir en un archivo asignado en memoria no implica ningún cambio de contexto o de llamada al sistema   gastos generales. Es tan simple como acceder a la memoria.

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

  •   
  • Buscar alrededor del mapeo implica manipulaciones de puntero triviales. No hay necesidad de la llamada al sistema lseek () .

  •   
     

Por estas razones, mmap () es una opción inteligente para muchas aplicaciones.

     

Desventajas de mmap ()

     

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

     
      
  • Las asignaciones de memoria son siempre un número entero de páginas de tamaño. Por lo tanto, la diferencia entre el tamaño del archivo de respaldo y un   el número entero de páginas se " se desperdicia " como espacio flojo. Para archivos pequeños, un   Se puede desperdiciar un porcentaje significativo del mapeo. Por ejemplo, con   Páginas de 4 KB, una asignación de 7 bytes desperdicia 4.089 bytes.

  •   
  • Las asignaciones de memoria deben caber en el espacio de direcciones del proceso. Con un espacio de direcciones de 32 bits, un gran número de asignaciones de varios tamaños   puede resultar en la fragmentación del espacio de direcciones, lo que dificulta la   Encuentra grandes regiones contiguas libres. Este problema, por supuesto, es mucho   menos aparente con un espacio de direcciones de 64 bits.

  •   
  • Existe una sobrecarga en la creación y el mantenimiento de las asignaciones de memoria y las estructuras de datos asociadas dentro del núcleo. Esta sobrecarga es   En general, se elimina por la eliminación de la copia doble mencionada en   La sección anterior, particularmente para los más grandes y de acceso frecuente.   archivos.

  •   
     

Por estas razones, los beneficios de mmap () se realizan de la mejor manera.   cuando el archivo asignado es grande (y, por lo tanto, cualquier espacio desperdiciado es un pequeño   porcentaje de la asignación total), o cuando el tamaño total de la asignación   El archivo es divisible por el tamaño de la página (y por lo tanto no se desperdicia   espacio).

El mapeo de memoria tiene el potencial de una gran ventaja de velocidad en comparación con el IO tradicional. Permite que el sistema operativo lea los datos del archivo de origen cuando se tocan las páginas del archivo asignado en la memoria. Esto funciona creando páginas con fallas, que el sistema operativo detecta y luego el sistema carga automáticamente los datos correspondientes del archivo.

Esto funciona de la misma manera que el mecanismo de paginación y generalmente se optimiza para E / S de alta velocidad al leer los datos en los límites y tamaños de la página del sistema (generalmente 4K), un tamaño para el cual la mayoría de las cachés del sistema de archivos están optimizadas. p>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top