Windows

       

Базовый адрес файла, проецируемого в память


Помните, как Вы с помощью функции VirtualAlloc указывали базовый адрес региона, резервируемого в адресном пространстве? Примерно так же можно указать системе спроектировать файл по определенному адресу — только вместо функции MapView PVOID нужна MapViewOfFileEx;

PVOID MapViewOfFileEx( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, PVOID pvBaseAddress);

Все параметры и возвращаемое этой функцией значение идентичны применяе мым в MapViewOfFile, кроме последнего параметра — pvBaseAddress. B нем можно за дать начальный адрес файла, проецируемого в память Как и в случае VirtualAlloc, ба повый адресдолжен быть кратным гранулярности выделения памяти в системе (обыч но 64 Кб), иначе MapViewOfFileEx вернет NULL. сообщив тем самым об ошибке.

Если Вы укажете базовый адрес, не кратный гранулярности выделения памяти, то MapViewOfFileEx в Windows 2000 завершится с ошибкой, и GetLastError вернет код 1132 (ERROR_MAPPED_ALIGNMENT) а в Windows 98 базовый адрес будет округлен до бли жайшего меньшего значения, кратного гранулярности выделения памяти.

Если система не в состоянии спроецировать файл по этому адресу (чаще всего из за того, что файл слишком велик и мог бы перекрыть другие регионы зарезервиро ванного адресного пространства), функция также возвращает NULL B этом случае она не пытается подобрать диапазон адресов, подходящий для данного файла Но если Вы укажете NUI,L в параметре pvBaseAddress, она поведет себя идентично MapViewOfFile.

MapViewOfFileEx удобна, когда механизм проецирования файлов в память приме няется для совместного доступа нескольких процессов к одним данным. Поясню Допустим, нужно спроецировать файл в память по определенному адресу; при этом два или более приложений совместно используют одну группу структур данных, со держащих указатели на другие структуры данных Отличный тому пример — связан ный список Каждый узел, или элемент, такого списка хранит адрес другого узла спис ка. Для просмотра списка надо узнать адрес первого узла, а затем сделать ссылку на то его поле, где содержится адрес следующего узла Но при использовании файлов, проецируемых в память, это весьма проблематично.




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

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

А можно и так Процесс, создающий связанный список, должен записывать в каж дый узел смещение следующего узла в пределах адресного пространства. Тогда про грамма, чтобы получить доступ к каждому узлу, будет суммировать это смещение с базовым адресом проецируемого файла. Несмотря на простоту, этот способ не луч ший: дополнительные операции замедлят работу программы и увеличат объем ее кода (так как компилятор для выполнения всех вычислений, естественно, сгенерирует до полнительный код) Кроме того, при этом способе вероятность ошибок значительно выше. Тем не менее он имеет право на существование, и поэтому компиляторы Micro soft поддерживают указатели со смещением относительно базового значения (based pointers), для чего предусмотрено ключевое слово _based

WINDOWS 98
В Windows 98 при вызове MapViewOfFileEx следует указывать адрес в диапазо не от 0x80000000 до 0xBFFFFFFF, иначе функция вернет NULL

WINDOWS 2000
В Windows 2000 при вызове MapViewOfFileEx следует указывать адрес в грани цах пользовательского раздела адресного пространства процесса, иначе фун кция вернет NULL.


Содержание раздела