Мапировать область памяти в адресное пространство процесса
#include <sys/mman.h>void * mmap( void *addr,size_t len,int prot,int flags,int fildes,off_t off );void * mmap64( void *addr,size_t len,int prot,int flags,int fildes,off64_t off );
NULL
или указатель на виртуальный адрес, по которому должна быть смапирована память в вызывающем процессе.0
или количество байт данных, подлежащих мапированию.<sys/mman.h>
: MAP_BELOW4G
добавлен в ЗОСРВ
«Нейтрино»
редакции 2018
NOFD
.
Если требуется мапирование физической памяти устройства, используйте функцию mmap_device_memory() вместо mmap().
Для архитекруры x86 если регистры устройства доступны в виде ресурсов памяти может использоваться функция mmap_device_memory(). В противном случае должна применяться функция mmap_device_io() для предоставления доступа к устройству, а также функции in8() и out8() для считывания и изменения значений регистров. В других архитектурах обе функции эквивалентны. |
libc
Функция mmap() производит мапирование в адресное пространство вызывающего процесса области памяти, ассоциированной с объектом filedes, начиная со смещения off и длиной len. Функция возвращает виртуальный адрес смапированной памяти. В качестве используемого объекта может быть выбран:
NOFD
Если аргумент fildes не соответствует NOFD
должен использоваться открытый для чтения файловый дескриптор независимо от того, что указано в аргументе prot; доступ на запись также требуется в случае, если задано разрешение PROT_WRITE
без MAP_PRIVATE
.
Процедура мапирования проиллюстрирована ниже.
В большинстве случаев использование аргумента addr не требуется, достаточно передать NULL
. В противном случае поведение функции определяется наличием или отсутствием флага MAP_FIXED:
MAP_FIXED
установлен MAP_FIXED
не установлен Существует две группы флагов, передаваемых через аргумент flags. Первая группа определяет тип памяти (флаги соответствуют маске MAP_TYPE
), который поддерживается функцией fork(). Должен быть выбран один из следующих типов:
В дополнение к основным типам мапирования могут переданы дополнительные флаги (через битовую операцию ИЛИ):
NOFD
). Функция mmap() выделяет память и зануляет ее (если не указан флаг MAP_NOINIT
). Это действие эквивалентно открытию /dev/zero
. MAP_ANON
часто используется в сочетании MAP_PRIVATE
, однако при создании разделяемой памяти с дочерними процессами, порождаемыми с помощью fork(), MAP_ANON
должен использоваться в сочетании с MAP_SHARED
. MAP_PHYS
| MAP_ANON
. Выделенная память будет размещена физически ниже порога в 16
Мб. Флаг важен для использовании DMA устройствами на шине ISA. MAP_PHYS
| MAP_ANON
. Выделенная память будет размещена физически ниже порога в 4
Гб. Флаг важен для использовании DMA устройствами, которые не поддерживают 64-битную
адресацию. Вы можете иметь несколько доступных на запись мапирований файла. Если осуществляется доступ к файлу через файловый дескриптор одновременно с мапированием его содержимого в адресное пространство, необходимо отдельно озаботиться вопросом обеспечения синхронизации доступа. Например, имеется возможность указать O_SYNC при использовании open(). |
Используйте флаг MAP_FIXED с осторожностью. Не все модели памяти поддерживают его. В общем случае следует исходить из того, что MAP_FIXED можно использовать только с адресами (и размерами), возвращаемыми mmap() без MAP_FIXED . |
MAP_FIXED
, сначала размапируется системой, используя ту же область памяти. Подробности см. в munmap(). MAP_PRIVATE
| MAP_ANON
страниц, до тех пор, пока к ним не будет осуществлет первый доступ по записи. Если флаг установлен, то в момент первого доступа по записи к невыделенной памяти поток получит сигнал SIGBUS
с кодом BUS_ADRERR
, что является триггером для менеджера памяти. MAP_ANON
| MAP_SHARED
и файловым дескриптором -1
) флаг MAP_LAZY
приводит к нефвной установке SHMCTL_LAZY
для объекта (подробнее см. shm_ctl()). UNMAP_INIT_OPTIONAL
, в противном случае данный флаг не будет иметь силы. Если одна и таже область памяти, принадлежащая файлу, смапирована дважды (с флагом MAP_NOSYNCFILE и без), менеджер памяти может некорректно определять сделаны ли изменения в файле с использованием MAP_NOSYNCFILE или без, что может привести к изменению файла даже в том случае, если это не предполагалось. |
MAP_PHYS
| MAP_ANON
. Предотвращает пересечение границы в 64
Кб при выделении памяти. Это может быть важно для некоторых DMA устройств. Если выделяется более 64
Кб, область памяти будет выровнена по границе 64
Кб. NOFD
. Если флаг используется без MAP_ANON
аргумент off определяет точный физический адрес ресурса (например, адрес буфера кадров видео памяти), что эквивалентно открытию /dev/mem
. MAP_ANON
функция mmap() выделяет физически непрерывную память, при этом аргумент off игнорируется. Могут использоваться дополнительные флаги, такие как MAP_NOX64K
и MAP_BELOW16M
, для включения специальных характеристик мапируемых областей памяти. MAP_ANON
для определения роли аллоцируемой памяти. Флаг носит информационный характер. Следующие флаги таже определены в <sys/mman.h>
, но использование их не рекомендовано:
MAP_PRIVATE
| MAP_ANON
вместо него. DCMD_PROC_MAPINFO
и DCMD_PROC_PAGEDATA
devctl(). Установка константы MAP_SYSRAM в качестве флага в функции mmap() приводит к ошибке EINVAL . |
Если аргумент fildes представляет объект типизированной памяти, открытый с использованием POSIX_TYPED_MEM_ALLOCATE
или POSIX_TYPED_MEM_ALLOCATE_CONTIG
флагов (см posix_typed_mem_open()), и при этом доступных ресурсов достаточно, функция mmap() производит мапирование len байт данных объекта, которые не были ранее аллоцированы любым процессом в системе, которым разрешен доступ к типизированной памяти. Если типизированная память не содержит требуемое количество ресурсов, вызов mmap() завершается с ошибкой.
Если аргумент fildes представляет объект типизированной памяти, открытый с использованием POSIX_TYPED_MEM_ALLOCATE_CONTIG
флага, мапируемая память является непрерывной в пределах заданного объекта. Если объект типизированной памяти был открыт с использованием POSIX_TYPED_MEM_ALLOCATE
, непрерывность не гарантируется. Если ни один из этих флаго не был использован, len байт данных, начиная со смещения off внутри объекта типизированной памяти, мапируется по аналогии с файлами или объектами разделяемой памяти. В этом случае, если два процесса мапируют типизированную память с одним и тем же смещением и длиной в рамках одного объекта, то они будут адресоваться к одной и той же области памяти.
Виртуальный адрес смапированного объекта или MAP_FAILED
в случае ошибки (при этом устанавливается errno).
PROT_WRITE
и MAP_SHARED
для файлового дескриптора fildes не доступного для записи. 0
или для флага MAP_FIXED
задан некорректный addr. RLIMIT_AS
и RLIMIT_DATA
параметры для setrlimit(). MAP_FIXED
, причем запрашиваемый диапазон адресов выходит за границы разрешенного адресного пространства процесса, либо недостаточно памяти для выполнения запроса. MAP_FIXED
, addr, len и off некорректно для запрашиваемого объекта. Открытие объекта разделяемой памяти и разделение доступа к нему между процессами:
fd = shm_open( "/datapoints", O_RDWR, 0777 );addr = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
Выделение физически непрерывного DMA буфера:
addr = mmap( 0, 262144, PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_PHYS | MAP_ANON, NOFD, 0 );
Мапирование файла в память, его модификация и последующая верификация изменений:
#include <stdlib.h>#include <stdio.h>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#define TESTSTRING "AAAAAAAAAA"int main( int argc, char *argv[] ){char buffer[80],filename[200] = "/tmp/try_it";int fd, file_size, ret, size_written, size_read;void *addr;/* Write the test string into the file. */unlink( filename );fd = open( filename, O_CREAT | O_RDWR, 0777 );if ( fd == -1 ){perror( "open" );exit( EXIT_FAILURE );}size_written = write( fd, TESTSTRING, sizeof( TESTSTRING ) );if ( size_written == -1 ){perror( "write" );exit( 0 );}printf( "Wrote %d bytes into file %s\n", size_written, filename );lseek( fd, 0L, SEEK_SET );file_size = lseek( fd, 0L, SEEK_END );printf( "Size of file = %d bytes\n", file_size );/* Map the file into memory. */addr = mmap( 0, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );if ( addr == MAP_FAILED ){perror( "mmap" );exit( EXIT_FAILURE );}/* Change the memory and synchronize it with the disk. */memset( addr, 'B', 5 );ret = msync( addr, file_size, MS_SYNC );if ( ret == -1 ){perror( "msync" );exit( 0 );}/* Close and reopen the file and then read its contents. */close( fd );fd = open( filename, O_RDONLY );if ( fd == -1 ){perror( "open" );exit( EXIT_FAILURE );}size_read = read( fd, buffer, sizeof( buffer ) );printf( "File content = %s\n", buffer );close( fd );return (EXIT_SUCCESS);}
mmap() — POSIX 1003.1 Memory Mapped Files, Shared Memory Objects, Typed Memory Objects; mmap64() — Поддержка больших файлов
mmap_device_io(), mmap_device_memory(), munmap(), msync(), posix_typed_mem_open(), setrlimit(), shm_open()
Предыдущий раздел: Описание API системной библиотеки