Когда я должен использовать mmap для доступа к файлам? - PullRequest
252 голосов
/ 03 ноября 2008

Среды POSIX предоставляют как минимум два способа доступа к файлам. Существуют стандартные системные вызовы open(), read(), write() и друзья, но есть также возможность использования mmap() для сопоставления файла с виртуальной памятью.

Когда предпочтительнее использовать один над другим? В чем заключаются их индивидуальные преимущества, включая два интерфейса?

Ответы [ 5 ]

281 голосов
/ 03 ноября 2008

mmap отлично подходит, если у вас есть несколько процессов, обращающихся к данным только для чтения из одного и того же файла, что типично для серверных систем, которые я пишу. mmap позволяет всем этим процессам совместно использовать одни и те же страницы физической памяти, экономя много памяти.

mmap также позволяет операционной системе оптимизировать операции подкачки. Например, рассмотрим две программы; программа A, которая считывает файл размером 1 МБ в буфер, создаваемый с помощью malloc, и программа B, которая отображает файл размером 1 МБ в память. Если операционная система должна выгрузить часть памяти А, она должна записать содержимое буфера для замены, прежде чем она сможет повторно использовать память. В случае B любые неизмененные страницы mmap'd могут быть немедленно использованы повторно, потому что ОС знает, как восстановить их из существующего файла, из которого они были mmap'd. (ОС может определить, какие страницы не изменены, изначально пометив доступные для записи страницы mmap как только для чтения и обнаружив ошибки сегментов, аналогично стратегии «Копировать при записи»).

mmap также полезен для межпроцессного взаимодействия. Вы можете отображать файл в режиме чтения / записи в процессах, которые должны взаимодействовать, а затем использовать примитивы синхронизации в области mmap (для этого и используется флаг MAP_HASSEMAPHORE).

В одном месте mmap может быть неудобным, если вам нужно работать с очень большими файлами на 32-битной машине. Это связано с тем, что mmap должен находить непрерывный блок адресов в адресном пространстве вашего процесса, который достаточно велик, чтобы соответствовать всему диапазону отображаемого файла. Это может стать проблемой, если ваше адресное пространство становится фрагментированным, где у вас может быть 2 ГБ свободного адресного пространства, но ни один из его отдельных диапазонов не может соответствовать отображению файла 1 ГБ. В этом случае вам, возможно, придется отобразить файл меньшими порциями, чем вы хотели бы, чтобы он соответствовал.

Другая потенциальная неловкость использования mmap в качестве замены для чтения / записи заключается в том, что вы должны начать отображение на смещениях размера страницы. Если вы просто хотите получить данные со смещением X, вам нужно исправить это смещение, чтобы оно было совместимо с mmap.

И, наконец, чтение / запись - единственный способ, которым вы можете работать с некоторыми типами файлов. mmap нельзя использовать для таких вещей, как pipe и ttys.

62 голосов
/ 04 ноября 2008

Я обнаружил, что mmap () не является преимуществом при чтении небольших файлов (до 16 КБ). Затраты на сбой страницы при чтении всего файла были очень высоки по сравнению с простым системным вызовом read (). Это потому, что ядро ​​иногда может полностью удовлетворить чтение в вашем интервале времени, то есть ваш код не переключается. С ошибкой страницы казалось более вероятным, что будет запланирована другая программа, что приведет к более высокой задержке файловой операции.

43 голосов
/ 24 мая 2010

mmap имеет преимущество, когда у вас есть произвольный доступ к большим файлам. Еще одним преимуществом является то, что вы обращаетесь к нему с помощью операций с памятью (memcpy, арифметика указателей), не беспокоясь о буферизации. Нормальный ввод-вывод может иногда быть довольно сложным при использовании буферов, когда у вас есть структуры больше, чем ваш буфер. Код для обработки, который часто трудно понять правильно, mmap, как правило, проще. Тем не менее, при работе с mmap существуют определенные ловушки. Как уже упоминалось, настройка mmap довольно дорогая, поэтому ее стоит использовать только для данного размера (в зависимости от машины к машине).

Для чисто последовательного доступа к файлу это также не всегда лучшее решение, хотя соответствующий вызов madvise может смягчить проблему.

Вы должны быть осторожны с ограничениями выравнивания вашей архитектуры (SPARC, itanium), при чтении / записи IO буферы часто правильно выровнены и не перехватываются при разыменовании приведенного указателя.

Вы также должны быть осторожны, чтобы не получить доступ за пределами карты. Это может легко произойти, если вы используете строковые функции на вашей карте, и ваш файл не содержит \ 0 в конце. Он будет работать большую часть времени, когда размер вашего файла не кратен размеру страницы, поскольку последняя страница заполнена 0 (отображаемая область всегда имеет размер, кратный размеру вашей страницы).

17 голосов
/ 27 сентября 2017

Помимо других приятных ответов, цитата из системного программирования Linux , написанная экспертом Google Робертом Лавом:

Преимущества mmap( )

Управление файлами с помощью mmap( ) имеет ряд преимуществ по сравнению с стандартные системные вызовы read( ) и write( ). Среди них:

  • Чтение и запись в отображенный в память файл позволяет избежать постороннее копирование, которое происходит при использовании системы read( ) или write( ) вызовы, где данные должны быть скопированы в буфер пространства пользователя и из него.

  • Помимо любых возможных сбоев страниц, чтение и запись в отображенный в память файл не приводит к системному вызову или переключению контекста. накладные расходы. Это так же просто, как доступ к памяти.

  • Когда несколько процессов отображают один и тот же объект в память, данные распределяются между всеми процессами. Только для чтения и общий доступ для записи отображения являются общими для всех; частные записи для записи имеют их страницы еще не COW (копировать при записи).

  • Поиск вокруг отображения включает в себя тривиальные манипуляции с указателями. Системный вызов lseek( ) не требуется.

По этим причинам mmap( ) - это разумный выбор для многих приложений.

Недостатки mmap( )

При использовании mmap( ) необходимо учитывать несколько моментов:

  • Отображения памяти всегда представляют собой целое число страниц по размеру. Таким образом, разница между размером файла поддержки и целое число страниц «впустую» как свободное место. Для небольших файлов значительный процент карт может быть потрачен впустую. Например, с 4 КБ страниц, 7-байтовое отображение тратит 4089 байт.

  • Отображения памяти должны вписываться в адресное пространство процесса. С 32-битным адресным пространством, очень большим количеством отображений различного размера может привести к фрагментации адресного пространства, что затрудняет найти большие свободные прилегающие регионы. Эта проблема, конечно, много менее заметен с 64-битным адресным пространством.

  • Существуют дополнительные затраты на создание и поддержание отображений памяти и связанных структур данных внутри ядра. Это накладные расходы как правило, устраняется путем устранения двойной копии, упомянутой в предыдущий раздел, особенно для больших и часто посещаемых файлов.

По этим причинам преимущества mmap( ) наиболее широко реализованы. когда сопоставленный файл большой (и, следовательно, в процентах от общего сопоставления), или когда общий размер сопоставленного файл равномерно делится на размер страницы (и, таким образом, пространство).

10 голосов
/ 03 ноября 2008

Отображение памяти имеет огромное преимущество в скорости по сравнению с традиционным вводом-выводом. Это позволяет операционной системе считывать данные из исходного файла при касании страниц в отображенном файле памяти. Это работает путем создания ошибочных страниц, которые ОС обнаруживает, а затем ОС автоматически загружает соответствующие данные из файла.

Это работает так же, как и механизм подкачки, и обычно оптимизируется для высокоскоростного ввода-вывода путем считывания данных по границам и размерам системных страниц (обычно 4 КБ) - размер, для которого оптимизировано большинство кэшей файловой системы.

...