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.