В вычислительной технике — mmap(2)
это POSIX- совместимый системный вызов Unix , который отображает файлы или устройства в память. Это метод ввода -вывода файлов, отображаемых в памяти . Он реализует подкачку по запросу , поскольку содержимое файла не считывается с диска сразу и изначально вообще не использует физическую оперативную память. Фактическое чтение с диска выполняется ленивым способом после доступа к определенному местоположению. После того, как сопоставление больше не требуется, указатели необходимо отменить с помощью . Информацией о защите — например, пометкой отображаемых регионов как исполняемых файлов — можно управлять с помощью , а специальную обработку можно применять с помощью .munmap(2)
mprotect(2)
madvise(2)
В Linux , macOS и BSD можно mmap
создавать несколько типов сопоставлений. Другие операционные системы могут поддерживать только часть из них; например, общие сопоставления могут оказаться непрактичными в операционной системе без глобальной VFS или кэша ввода-вывода.
Оригинальный дизайн файлов, отображаемых в памяти, зародился в операционной системе TOPS-20 . mmap
и связанные с ним системные вызовы были разработаны как часть версии Unix Berkeley Software Distribution (BSD). Их API уже был описан в Системном руководстве 4.2BSD, хотя он не был реализован ни в этой версии, ни в 4.3BSD. [1] Однако компания Sun Microsystems реализовала именно этот API в своей операционной системе SunOS . Разработчики BSD из Калифорнийского университета в Беркли безуспешно просили Sun пожертвовать свою реализацию; Вместо этого 4.3BSD-Reno поставлялась с реализацией, основанной на системе виртуальной памяти Mach . [2]
Отображение на основе файлов отображает область виртуальной памяти процесса на файлы; то есть чтение этих областей памяти приводит к чтению файла. Это тип сопоставления по умолчанию.
Анонимное сопоставление отображает область виртуальной памяти процесса, не поддерживаемую каким-либо файлом. Содержимое инициализируется нулевым значением. [3] В этом отношении анонимное сопоставление похоже на malloc и используется в некоторых реализациях malloc для определенных выделений, особенно больших. Анонимные сопоставления не являются частью стандарта POSIX, но реализованы почти во всех операционных системах с помощью флагов MAP_ANONYMOUS
и MAP_ANON
.
Если сопоставление является общим ( MAP_SHARED
флаг установлен), то оно сохраняется при разветвлении процесса (с использованием fork(2)
системного вызова). Таким образом, записи в сопоставленную область в одном процессе немедленно становятся видимыми во всех связанных (родительских, дочерних или родственных) процессах. Если отображение является общим и поддерживается файлом (не MAP_ANONYMOUS
), базовый файловый носитель гарантированно будет записан только после того, как он будет передан msync(2)
системному вызову. Напротив, если сопоставление является частным ( MAP_PRIVATE
флаг установлен), изменения не будут видны другим процессам и не будут записаны в файл.
Процесс, читающий или записывающий в базовый файл, не всегда будет видеть те же данные, что и другой процесс, сопоставивший файл, поскольку сегменты файла копируются в ОЗУ и лишь периодически сбрасываются на диск. Синхронизацию можно вызвать принудительно с помощью вызова msync(2)
.
Использование mmap для файлов может значительно снизить нагрузку на память для приложений, обращающихся к одному и тому же файлу; они могут совместно использовать область памяти, которую охватывает файл, вместо того, чтобы загружать файл для каждого приложения, которому требуется к нему доступ. Это означает, что mmap(2) иногда используется для межпроцессного взаимодействия (IPC). В современных операционных системах mmap(2) обычно предпочтительнее функции общей памяти System V IPC . [4]
Основное различие между общей памятью System V (shmem) и вводом-выводом, отображаемым в памяти (mmap), заключается в том, что общая память System V является постоянной: если она не удалена явно процессом, она сохраняется в памяти и остается доступной до выключения системы. . Память mmap не является постоянной между выполнением приложения (если она не поддерживается файлом).
#include <sys/types.h> #include <sys/mman.h> #include <err.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <строка.h> #include <unistd.h> /* Этот пример показывает, как mmap /dev/zero эквивалентен использование анонимной памяти (MAP_ANON), не связанной ни с одним файлом. NB MAP_ANONYMOUS или MAP_ANON поддерживаются большинством UNIX. версии, удаляя первоначальную цель /dev/zero.*//* Не работает в OS X или macOS, где невозможно выполнить mmap через /dev/zero */int main ( недействительный ) { const char str1 [] = "строка 1" ; const char str2 [] = "строка 2" ; pid_t parpid = getpid (), childpid ; интервал ФД = -1 ; char * анон , * ноль ; if (( fd = open ( "/dev/zero" , O_RDWR , 0 )) == -1 ) ошибка ( 1 , «открыть» ); анон = ( символ * ) ммап ( NULL , 4096 , PROT_READ | PROT_WRITE , MAP_ANON | MAP_SHARED , -1 , 0 ); ноль = ( char * ) mmap ( NULL , 4096 , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 ); если ( анон == MAP_FAILED || ноль == MAP_FAILED ) errx ( 1 , "либо mmap" ); стркпи ( анон , стр1 ); стркпи ( ноль , стр1 ); printf ( "PID %d: \t анонимный %s, %s с нулевой поддержкой \n " , parpid , anon , ноль ); переключатель (( childpid = fork ())) { Дело 1 : ошибаться ( 1 , «вилка» ); /* НЕДОСТИЖЕН */ случай 0 : childpid = getpid (); printf ( "PID %d: \t анонимный %s, %s с нулевой поддержкой \n " , childpid , anon , ноль ); спать ( 3 ); printf ( "PID %d: \t анонимный %s, %s с нулевой поддержкой \n " , childpid , anon , ноль ); munmap ( анон , 4096 ); munmap ( ноль , 4096 ); закрыть ( ФД ); вернуть EXIT_SUCCESS ; } спать ( 2 ); стркпи ( анон , стр2 ); стркпи ( ноль , стр2 ); printf ( "PID %d: \t анонимный %s, %s с нулевой поддержкой \n " , parpid , anon , ноль ); munmap ( анон , 4096 ); munmap ( ноль , 4096 ); закрыть ( ФД ); вернуть EXIT_SUCCESS ; }
пример вывода:
PID 22475: анонимная строка 1, строка с нулевой поддержкой 1.PID 22476: анонимная строка 1, строка с нулевой поддержкой 1.PID 22475: анонимная строка 2, строка с нулевой поддержкой 2.PID 22476: анонимная строка 2, строка с нулевой поддержкой 2.
Системный вызов mmap использовался в различных реализациях баз данных в качестве альтернативы реализации пула буферов, хотя это создавало другой набор проблем, которые реально можно было решить только с помощью пула буферов. [5]