Отображение файла на адресное пространство процесса

Отображение файла на адресное пространство процесса

Следующим шагом является распределение виртуального адресного пространства и отображение на него файла с использованием объекта отображения. С точки зрения программиста этот процесс распределения памяти аналогичен тому, который обсуждался при рассмотрении функции HeapAlloc, хотя и делает это намного грубее, оперируя более крупными блоками. В результате этого распределения возвращается указатель на распределенный блок, или представление файла (file view); различие состоит в том, что этот распределенный блок является отображением пользовательского файла, а не файла подкачки. Объект отображения файла играет ту же роль, что и куча в случае использования функции HeapAlloc.

LPVOID MapViewOfFile(HANDLE hMapObject, DWORD dwAccess, DWORD dwOffsetHigh, DWORD dwOffsetLow, SIZE_T cbMap)

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

Параметры

hMapObject — дескриптор объекта отображения файла, возвращенный функцией CreateFileMapping или OpenFileMapping.

dwAccess — этот параметр должен быть совместимым с разрешенными типами доступа к объекту отображения. Тремя возможными флаговыми значениями являются FILE_MAP_WRITE, FILE_MAP_READ и FILE_MAP_ALL_ACCESS. (Последний флаг является результатом применения поразрядной операции "или" к двум предыдущим флагам).

dwOffsetHigh и dwOffsetLow — соответственно, старшая и младшая 32-битовые части смещения начала отображаемого участка в файле. Значение этого начального адреса должно быть кратным 64 Кбайт. Чтобы начало отображаемого участка совпадало с началом файла, оба параметра следует задать равными 0. 

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

Функция MapViewOfFileEx аналогична функции MapViewOfFile, но дополнительно позволяет указать при вызове начальный адрес памяти для отображенного представления. Например, в качестве такого адреса может быть указан адрес массива в пространстве данных программы. В Windows, если затребованная область памяти уже используется для отображения, выполнение этой функции завершится с ошибкой.

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

BOOL UnmapViewOfFile(LPVOID lpBaseAddress) 

Взаимосвязь между адресным пространством процесса и отображаемым файлом проиллюстрирована на рис. 5.3. 

Рис. 5.З. Отображение представления файла на адресное пространство процесса

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

В силу этого идея получения доступа к отображаемому файлу с помощью функций ReadFile и WriteFile не сулит ничего хорошего, поскольку согласованность данных при этом не гарантируется. С другой стороны, представления файла для процессов, получающих совместный доступ к нему через разделяемую память, будут согласованными. Если один процесс изменяет какой-либо участок памяти в области отображения файла, то другой процесс при получении доступа к соответствующему участку в своей области отображения файла получит измененные данные. Этот механизм проиллюстрирован на рис. 5.4, из которого следует, что согласованность отображенных представлений файла в двух процессах (РА и РВ) действительно обеспечивается, поскольку виртуальным адресам данных в обоих процессах, несмотря на то, что эти адреса различны, соответствуют одни и те же участки физической памяти; Естественным образом связанная с этим тема синхронизации процессов обсуждается в главах 8—10.[24]

Рис. 5.4. Разделяемая память

В UNIX (выпуски SVR4 и 4.3+BSD) поддерживается функция mmap, аналогичная функции MapViewOfFile. В ее параметрах указывается та же информация, за исключением того, что объект отображения отсутствует.

Эквивалентом функции UnMapViewOfFile является функция munmap.

Для функций CreateFileMapping и OpenFileMapping эквиваленты отсутствуют. Любой обычный файл может непосредственно отображаться. В UNIX отображение файлов для разделения памяти не используется, и для этих целей предусмотрены специальные функции API, а именно, shmctl, shmat и shmdt.