ммап
В вычислениях , 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 не является постоянной между выполнением приложения (если она не поддерживается файлом).
Пример использования на языке программирования C
[ редактировать ]#include <sys/types.h>
#include <sys/mman.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* This example shows how an mmap of /dev/zero is equivalent to
using anonymous memory (MAP_ANON) not connected to any file.
N.B. MAP_ANONYMOUS or MAP_ANON are supported by most UNIX
versions, removing the original purpose of /dev/zero.
*/
/* Does not work on OS X or macOS, where you can't mmap over /dev/zero */
int main(void)
{
const char str1[] = "string 1";
const char str2[] = "string 2";
pid_t parpid = getpid(), childpid;
int fd = -1;
char *anon, *zero;
if ((fd = open("/dev/zero", O_RDWR, 0)) == -1)
err(1, "open");
anon = (char*)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
zero = (char*)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (anon == MAP_FAILED || zero == MAP_FAILED)
errx(1, "either mmap");
strcpy(anon, str1);
strcpy(zero, str1);
printf("PID %d:\tanonymous %s, zero-backed %s\n", parpid, anon, zero);
switch ((childpid = fork())) {
case -1:
err(1, "fork");
/* NOTREACHED */
case 0:
childpid = getpid();
printf("PID %d:\tanonymous %s, zero-backed %s\n", childpid, anon, zero);
sleep(3);
printf("PID %d:\tanonymous %s, zero-backed %s\n", childpid, anon, zero);
munmap(anon, 4096);
munmap(zero, 4096);
close(fd);
return EXIT_SUCCESS;
}
sleep(2);
strcpy(anon, str2);
strcpy(zero, str2);
printf("PID %d:\tanonymous %s, zero-backed %s\n", parpid, anon, zero);
munmap(anon, 4096);
munmap(zero, 4096);
close(fd);
return EXIT_SUCCESS;
}
пример вывода:
PID 22475: anonymous string 1, zero-backed string 1 PID 22476: anonymous string 1, zero-backed string 1 PID 22475: anonymous string 2, zero-backed string 2 PID 22476: anonymous string 2, zero-backed string 2
Использование в реализациях баз данных
[ редактировать ]Системный вызов mmap использовался в различных реализациях баз данных в качестве альтернативы реализации буферного пула, хотя это создавало другой набор проблем, которые реально можно было решить только с использованием буферного пула. [5]
См. также
[ редактировать ]- Виртуальная память , когда адресного пространства больше, чем физической памяти.
- Пейджинг для реализации виртуальной памяти
- Кэш страниц для механизма кэширования диска, используемого mmap.
- Пейджинг по запросу для схемы, реализованной с помощью mmap
Ссылки
[ редактировать ]- ^ Уильям Джой ; Эрик Купер; Роберт Фабри ; Сэмюэл Леффлер ; Кирк МакКьюсик ; Дэвид Мошер (1983). 4.2BSD Системное руководство (PDF) (Отчет). исследования компьютерных систем Группа Калифорнийского университета в Беркли .
- ^ МакКьюсик, Маршалл Кирк (1999). «Двадцать лет Berkeley Unix: от собственности AT&T к свободно распространяемому». Открытые исходные коды: голоса революции открытого исходного кода . О'Рейли.
- ^ «mmap(2) — страница руководства Linux» .
- ^ Керриск, Майкл (2010). Интерфейс программирования Linux: справочник по системному программированию Linux и UNIX . Сан-Франциско: Пресса без крахмала. п. 1116. ИСБН 978-1-59327-291-3 . OCLC 728672600 .
- ^ «Вы уверены, что хотите использовать MMAP в своей системе управления базами данных?» . db.cs.cmu.edu . Проверено 4 июля 2023 г.
Дальнейшее чтение
[ редактировать ]- Описание из стандарта POSIX
- Отличия:
- Окна
- Функция MapViewOfFile win32 в некоторой степени эквивалентна mmap.
- Еще пример исходного кода:
- SharedHashFile — хеш-таблица общей памяти с открытым исходным кодом, реализованная с помощью mmap().