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).
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.