Возможна ли запись файлов в память? - PullRequest
2 голосов
/ 27 октября 2009

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

  • есть один открытый для записи, а потом решите не сохранять его
  • открыли для чтения, а потом решили сохранить

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

Я перепробовал много комбинаций флагов, использованных для создания сопоставления файлов, но ни одна из них, похоже, не обеспечивает гибкости сохранения по требованию. Кто-нибудь может подтвердить, что это так? Наше приложение написано на Delphi, но оно использует стандартный Windows API для создания отображения, в нашем случае

FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READWRITE, 0, 2 * 65536, nil);
FBasePointer := MapViewOfFile(FileMapHandle, FILE_MAP_WRITE, FileOffsetHigh,
FileOffsetLow, NumBytes);

Ответы [ 2 ]

5 голосов
/ 27 октября 2009

Не думаю, что ты можешь. Под этим я подразумеваю, что вы можете быть в состоянии, но для меня это не имеет никакого смысла: -)

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

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

Обновление:

Задумывались ли вы о возможности при сохранении удалить исходный файл и просто переименовать временный файл в исходное имя файла? Это, вероятно, будет гораздо быстрее, чем копирование 1G данных из временного в исходное. Таким образом, если вы не хотите, чтобы он был сохранен, просто удалите временный файл и сохраните его.

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

3 голосов
/ 30 октября 2009

Возможно, но нетривиально.

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

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

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

Если пользователь решил сохранить, у вас есть немного более сложная задача. Теперь вам нужно выяснить, какие части файла изменились. Эти изменения находятся в памяти, и вам необходимо повторно применить их к исходному файлу. Вы можете сделать это с помощью Page Guards . Поэтому, когда пользователь решает сохранить, скопировать все измененные страницы в отдельный блок памяти, переназначить (неизмененный) файл для записи и применить изменения.

...