Мапировать область памяти в адресное пространство процесса
#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 системной библиотеки