MMAP(2)

NOMBRE
mmap, munmap - ubica o elimina ficheros o dispositivos en memoria

SINOPSIS
#include <sys/mman.h>

caddr_t mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);

int munmap(void *start, size_t length);

DESCRIPCIÓN
La función mmap intenta ubicar length bytes comenzando en el desplazamiento offset desde el fichero (u otro objeto) especificado por el descriptor de fichero fd en memoria, preferiblemente en la dirección start. Esta última dirección es una sugerencia y normalmente se especifica como 0. El lugar donde es ubicado el objeto es devuelto por mmap, y nunca vale 0. El argumento prot describe la protección de memoria deseada. (y no debe entrar en conflicto con el modo de apertura del fichero). Puede valer PROT_NONE o ser la combinación mediante la operación OR de una o más de las otras banderas PROT_*.

PROT_EXEC
    Las páginas deben ser ejecutadas.

PROT_READ
    Las páginas deben ser leídas.

PROT_WRITE
    Las páginas deben ser escritas.

PROT_NONE
    Las páginas no pueden ser accedidas.

El parámetro flags especifica el tipo de objeto insertado, las opciones de asociación y si las modificaciones hechas a la copia insertada en memoria son privadas al proceso o son compartidas por otras referencias. Tiene los bits:

MAP_FIXED
    No seleccionar una dirección diferente a la especificada. Si la dirección especificada no puede ser utilizada, mmap fallará. Si MAP_FIXED es especificado, start debe ser un múltiplo del tamaño de página. Utilizar esta opción es desaconsejable.

MAP_SHARED
    Comparte este área con todos los otros objetos que señalan a este objeto. Almacenar en la región es equivalente a escribir en el fichero. El fichero puede no actualizarse hasta que se llame a msync(2) o munmap(2).

MAP_PRIVATE
    Crear un área privada "copy-on-write". Almacenar en la región no afecta al fichero original. Es indefinido si los cambios hechos al fichero después de la llamada a mmap son visibles en la región mapeada.

Debe especificarse exactamente uno de los parÃ¡metros MAP_SHARED o MAP_PRIVATE.

Los tres parámetros anteriores están descritos en POSIX.1b (formalmente POSIX.4) y Linux también reconoce los siguientes parámetros no estándares:

MAP_DENYWRITE
    Este parámetro es ignorado. (Anteriormente, indicaba que los intentos de escritura al fichero subyacente deberían fallar con ETXTBUSY. Pero ésto era fuente de ataques de denegación -de-servicio.)

MAP_EXECUTABLE
    Este parámetro es ignorado.

MAP_NORESERVE
    (Usado junto con MAP_PRIVATE.) No reserva páginas del espacio de intercambio para esta correspondencia. Cuando se reserva espacio de intercambio, se tiene la garantía de que es posible modificar esta región privada. Cuando no se reserva puede obtenerse una violación de segmento al escribir si no hay memoria disponible.

MAP_LOCKED
    Este parámetro es ignorado.

MAP_GROWSDOWN
    Usado para pilas. Indica al sistema VM del núcleo que la correspondencia podría extenderse hacia abajo en memoria.

MAP_ANONYMOUS
    La correspondencia no está respaldada por ningún fichero; los argumentos fd y offset son ignorados. Este parámetro conjuntamente con MAP_SHARED está implementado desde Linux 2.4.

MAP_ANON
    Sinónimo para MAP_ANONYMOUS. Desaconsejado.

MAP_FILE
    Parámetro de compatibilidad. Ignorado.

MAP_32BIT
    Ubica la correspondencia dentro de los primeros 2 GB del espacio de direcciones del proceso. Es ignorado cuando MAP_FIXED está activo. Este parámetro está soportado actualmente sólo sobre x86-64 para programas de 64 bits.

Algunos sistemas documentan los parámetros adicionales MAP_AUTOGROW, MAP_AUTORESRV, MAP_COPY, y MAP_LOCAL.

fd debe ser un descriptor de fichero válido, a menos que MAP_ANONYMOUS esté activo, en cuyo caso el argumento es ignorado.

offset debe ser un múltiplo del tamaño de página como lo devuelve getpagesize(2).

La memoria asociada con mmap es conservada después de fork(2), con los mismos atributos.

Un fichero es ubicado en múltiplos del tamaño de página. Para un fichero que no sea múltiplo del tamaño de página, la memoria restante es puesta a cero cuando se ubica, y las escrituras a esa región no son llevadas al fichero. El efecto de cambiar el tamaño del fichero subyacente a una correspondencia en aquellas páginas que correspondan a regiones añadidas o eliminadas del fichero es indefinido.

La llamada al sistema munmap borra las ubicaciones para el rango de direcciones especificado, y produce referencias a las direcciones dentro del rango a fin de generar referencias a memoria inválidas. La región es también desubicada automáticamente cuando el proceso termina. Por otra parte, cerrar el descriptor de fichero no desubica la región.

La dirección start debe ser un múltiplo del tamaño de página. Todas las páginas que contengan una parte del rango indicado son desubicadas, y referencias posteriores a estas páginas generarán una violación de segmento. No se considera un error si el rango indicado no contiene páginas con correspondencia.

Para correspondencias respaldadas por fichero, el campo st_atime para el fichero ubicado puede ser actualizado en cualquier instante entre la llamada mmap() y la desubicación correspondiente; la primera referencia a una página con correspondencia actualizará el campo si no lo ha sido ya.

Los campos st_ctime y st_mtime para un fichero ubicado con PROT_WRITE y MAP_SHARED serán actualizados después de una escritura a la región ubicada, y antes de una llamada posterior a msync() con la opción MS_SYNC o MS_ASYNC, si alguna procede.

VALOR DEVUELTO
Si ha funcionado mmap devuelve un puntero al área reservada. En caso de error, es devuelto -1, y errno es modificado apropiadamente. Si ha funcionado munmap devuelve 0, si hay error -1, y errno es fijada (probablemente a EINVAL).

OBSERVACIONES
Es dependiente de la arquitectura si PROT_READ incluye a PROT_EXEC o no. Los programas portables deberían siempre activar PROT_EXEC si intentan ejecutar código en la nueva región ubicada.

ERRORES

EBADF
    fd no es un descriptor de fichero válido (y MAP_ANONYMOUS no ha sido fijado).

EACCES
    Un descriptor de fichero hace referencia a un fichero no regular. O bien se solicitó MAP_PRIVATE, pero fd no está abierto para lectura. O bien se solicitó MAP_SHARED y PROT_WRITE está activo, pero fd no está abierto en modo lectura/escritura (O_RDWR). O bien PROT_WRITE está activo, pero el fichero es sólo para añadir.

EINVAL
    No es correcto start o length o offset. (E.g., son demasiado grandes, o no están alineados en los limites de un valor múltiplo de PAGESIZE).

ETXTBSY
    MAP_DENYWRITE fue fijado pero el objeto especificado por fd está abierto para escritura.

EAGAIN
    El fichero ha sido bloqueado, o se ha bloqueado una cantidad excesiva de memoria.

ENOMEM
    No hay memoria disponible, o el número máximo de correspondencias del proceso habría sido excedido.

ENODEV
    El sistema de ficheros subyacente del fichero especificado no soporta la correspondencia de memoria.

El uso de una región ubicada puede resultar en estas señales:

SIGSEGV
    Intento de escritura en una región especificada a mmap como solo-lectura.

SIGBUS
    Intento de acceso a una porción del buffer que no se corresponde con el fichero (por ejemplo, más allá del fin del fichero, incluyendo el caso en el que otro proceso ha truncado el fichero).

CONFORME A
SVr4, POSIX.1b (formalmente POSIX.4), 4.4BSD, SUSv2. SVr4 documenta los códigos de error ENXIO y ENODEV. SUSv2 documenta ls códigos de error adicionales EMFILE y EOVERFLOW.

MAP_32BIT es una extensión de Linux.

VÉASE TAMBIÉN
getpagesize(2), mmap2(2), mremap(2), msync(2), shm_open(2), B.O. Gallmeister, POSIX.4, O'Reilly, pp. 128-129 and 389-391.