Вопрос

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

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

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

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

FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READWRITE, 0, 2 * 65536, nil);
FBasePointer := MapViewOfFile(FileMapHandle, FILE_MAP_WRITE, FileOffsetHigh,
FileOffsetLow, NumBytes);
Это было полезно?

Решение

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

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

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

Обновлять:

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

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

Другие советы

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

Вы должны понимать основы отображения памяти и разницу между тремя режимами отображения файлов в памяти.Оба выделяют часть вашего виртуального адресного пространства и создают запись сопоставления во внутренней таблице.Физическая оперативная память изначально не выделяется.Следовательно, когда вы ДЕЙСТВИТЕЛЬНО пытаетесь получить доступ к памяти, происходит сбой ЦП, и ОС необходимо исправить.Для этого он копирует содержимое файла в ОЗУ и сопоставляет ОЗУ с вашим процессом по адресу сбоя.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top