Отображение файла в память

18-10-2023

Перейти к: навигация, поиск

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

Достоинства метода

Альтернативой отображению может служить прямое чтение файла или запись в файл. Такой способ работы менее удобен по следующим причинам:

  1. Необходимо постоянно помнить текущую позицию файла и вовремя её передвигать на нужное место, в которое необходимо записать или из которого необходимо прочитать.
  2. Каждый вызов смены/чтения текущей позиции, записи/чтения — это системный вызов, который приводит к потере времени.
  3. Для работы через чтение/запись всё равно приходится выделять буферы определённого размера, таким образом, в общем виде работа состоит из трёх этапов: чтение в буфер -> модификация данных в буфере -> запись в файл. При отображении же работа состоит только из одного этапа: модификация данных в определённой области памяти.

Дополнительным преимуществом использования отображения является меньшая по сравнению с чтением/записью нагрузка на операционную систему — дело в том, что при использовании отображений операционная система не загружает в память сразу весь файл, а делает это по мере необходимости, блоками размером со страницу памяти (как правило 4 килобайта). Таким образом, даже имея небольшое количество физической памяти (например 32 мегабайта), можно легко отобразить файл размером 100 мегабайт или больше, и при этом для системы это не приведет к большим накладным расходам. Также выигрыш происходит и при записи из памяти на диск: если вы обновили большое количество данных в памяти, они могут быть одновременно (за один проход головки над диском) сброшены на диск.

Файл, отображенный на память, удобен также тем, что можно достаточно легко менять его размер и при этом (после переотображения) получать в своё распоряжение непрерывный кусок памяти нужного размера. С динамической памятью такой трюк не всегда возможен из-за явления фрагментации. Когда же мы работаем с отображенным на память файлом — менеджер памяти автоматически настраивает процессор так, что странички ОЗУ, хранящие соседние фрагменты файла, образуют непрерывный диапазон адресов.

Недостатки

Основная причина, по которой следует пользоваться отображением — выигрыш в производительности. Однако, необходимо помнить о компромиссах, на которые придется пойти. Обычный ввод-вывод чреват накладными расходами на дополнительные системные вызовы и лишнее копирование данных, использование отображений чревато замедлениями из-за страничных ошибок доступа. Допустим, страница, относящаяся к нужному файлу, уже лежит в кэше, но не ассоциирована с данным отображением. Если она была изменена другим процессом, то попытка ассоциировать её с отображением может закончится неудачей и привести к необходимости повторно зачитывать данные с диска, либо сохранять данные на диск. Таким образом, хотя программа и делает меньше операций для доступа через отображение, в реальности операция записи данных в какое-то место файла может занять больше времени, чем с использованием операций файлового ввода-вывода (при том, что в среднем использование отображений даёт выигрыш).

Другой недостаток в том, что размер отображения зависит от используемой архитектуры. Допустим, 32-битные архитектуры (Intel 386, ARM 9) не могут создавать отображения длиной более 4 Гб.

Применение

Пожалуй, наиболее общий случай, когда применяется отображение файлов на память — загрузка процесса в память (это справедливо и для Microsoft Windows и для Unix-подобных систем). После запуска процесса операционная система отображает его файл на память, для которой разрешено выполнение (атрибут executable). Большинство систем, использующих отображение файлов используют методику загрузка страницы по первому требованию, при которой файл загружается в память не целиком, а небольшими частями, размером со страницу памяти, при этом страница загружается только тогда, когда она действительно нужна.[1] В случае с исполняемыми файлами такая методика позволяет операционной системе держать в памяти только те части машинного кода, которые реально нужны для выполнения программы.

Другой общеупотребимый случай использования отображений — создание разделяемых несколькими процессами фрагментов памяти. В современных ОС (использующих защищенный режим), процесс, вообще говоря, не позволяет другим процессам обращаться к «своей» памяти. Программы, которые пытаются обратиться не к своей памяти генерируют исключительные ситуации invalid page faults или segmentation violation. Есть несколько способов безопасно (без возникновения исключительных ситуаций) сделать память доступной нескольким процессам и использование файлов, отображенных на память — один из наиболее популярных способов сделать это. Два или более приложений могут одновременно отобразить один и тот же физический файл на свою память и обратиться к этой памяти.

Платформы, поддерживающие отображение файлов на память

Большинство современных операционных систем или оболочек поддерживают те или иные формы работы с файлами, отображенными на память. Например, функция mmap()[2] , создающая отображение для файла с данным дескриптором, начиная с некоторого места в файле и с некоторой длиной — является частью спецификации POSIX. Таким образом, огромное количество POSIX-совместимых систем, таких как UNIX, Linux, FreeBSD, Mac OS X [3] или OpenVMS, поддерживают общий механизм отображения файлов. ОС Microsoft Windows также поддерживает определённый API для этих целей, например, CreateFileMapping() [4].

Примеры

Python

import mmap
import os
filename = "/tmp/1.txt"
file = open(filename, "r+b")
size = os.path.getsize(filename)
data = mmap.mmap(file.fileno(), size)
print data[0:5] ## выведет первые 5 символов файла
print data.read(size) ## выведет содержимое файла целиком
 
string = "Hello from Python!!!"
data.resize( size+len(string)) # увеличивам "отображённый размер" на размер строки, которую хотим вписать
data.seek(size) # Устанавливаем курсор в конец файла
data.write( string ) # и дописываем строку в конец файла
data.close()
file.close() ## Закрываем файл

Ссылки

  1. Demand Paging
  2. Memory Mapped Files
  3. Apple — Mac OS X Leopard — Technology — UNIX
  4. CreateFileMapping Function (Windows)

Отображение файла в память.

© 2011–2023 stamp-i-k.ru, Россия, Барнаул, ул. Анатолия 32, +7 (3852) 15-49-47