Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
os_a_win.doc
Скачиваний:
15
Добавлен:
17.11.2019
Размер:
715.26 Кб
Скачать

Функции менеджера памяти Windows

Для выделения регионов памяти в Windows используется функция VirtualAlloc. Эта функция может решать две задачи – резервирование региона памяти за приложением и передача физической памяти зарезервированному региону.

LPVOID VirtualAlloc(

LPVOID lpAddress, // region to reserve or commit

SIZE_T dwSize, // size of region

DWORD flAllocationType, // type of allocation

DWORD flProtect // type of access protection

);

Параметр flAllocationType определяет, какую операцию необходимо выполнить. Основными значениями этого параметра являются MEM_RESERVE – резервирование региона памяти за приложением и MEM_COMMIT – передать физическую память зарезервированным страницам. Оба эти параметра можно указать одновременно.

С помощью параметров lpAddress и dwSize можно задать адрес начала и размер области, которую следует зарезервировать или выделить. В случае если расположение региона памяти не принципиально, в качестве значения lpAddress можно задать NULL. Однако если вы запрашиваете выделение страниц памяти под заранее зарезервированную область, то адрес указывать обязательно.

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

Параметр flProtect позволяет задать тип доступа к выделяемой памяти. Он может принимать следующие значения, соответствующие правам доступа к памяти Windows: PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD, PAGE_NOACCESS, PAGE_NOCACHE.

Функция VirtualAlloc возвращает базовый адрес блока, который был зарезервирован или выделен. В случае ошибки она возвращает значение NULL.

Вернуть физическую память или освободить зарезервированный регион можно с помощью функции VirtualFree:

BOOL VirtualFree(

LPVOID lpAddress, // address of region

SIZE_T dwSize, // size of region

DWORD dwFreeType // operation type

);

Также как в случае VirtualAlloc можно указать необходимую операцию с помощью параметра dwFreeType. Значение MEM_DECOMMIT говорит о том, что необходимо освободить физическую память внутри зарезервированного региона, MEM_RELEASE – о том, что необходимо снять резервирование.

При освобождении страниц можно указать адрес и размер освобождаемой области, используя параметры lpAddress и dwSize. При этом освобождаемый регион также будет расширен до границы страниц, на которые он попадает. Снятие резервирования возможно только целиком для всего блока, как он был зарезервирован. Размер блока при этом указывать не надо.

Функция возвращает логическое значение, которое говорит об успешности выполнения операции.

Проецируемые в память файлы

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

Создание проекции файла производится в три этапа:

  1. создание объекта ядра типа файл;

  2. создание объекта ядра проекция файла;

  3. проецирование части файла в адресное пространство процесса.

Для создания объекта файл необходимо воспользоваться функцией CreateFile, также как и при обычном открытии файла:

HANDLE CreateFile(

LPCTSTR lpFileName, // file name

DWORD dwDesiredAccess, // access mode

DWORD dwShareMode, // share mode

LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD

DWORD dwCreationDisposition, // how to create

DWORD dwFlagsAndAttributes, // file attributes

HANDLE hTemplateFile // handle to template file

);

Имя файла передается в параметре lpFileName. Файл должен быть открыт с правами доступа (dwDesiredAccess), соответствующими правам доступа, которые будут в дальнейшем использоваться для доступа к памяти. Параметр dwShareMode позволяет задать режим доступа к файлу для других процессов. Рекомендуется использовать эксклюзивный доступ, передав значение 0. Параметр lpSecurityAttributes позволяет задать обычные для объектов ядра права доступа к объекту. dwCreationDisposition определяет режим открытия файла. Для открытия существующего файла он должен быть равен OPEN_EXISTING. При создании проекции файла параметры dwFlagsAndAttributes и hTemplateFile можно задать равными 0 и NULL соответственно.

В случае ошибки функция CreateFile возвращает значение INVALID_HANDLE_VALUE.

Следующий этап это создание объекта ядра проекция файла. Это можно сделать с помощью функции CreateFileMapping:

HANDLE CreateFileMapping(

HANDLE hFile, // handle to file

LPSECURITY_ATTRIBUTES lpAttributes, // security

DWORD flProtect, // protection

DWORD dwMaximumSizeHigh, // high-order DWORD of size

DWORD dwMaximumSizeLow, // low-order DWORD of size

LPCTSTR lpName // object name

);

Прежде всего, необходимо передать ей в параметре hFile дескриптор открытого файла, который будет отображаться в память. Параметр lpAttributes определяет права доступа к создаваемому объекту ядра. Флаги dwProtect определяют права доступа к отображению памяти и могут принимать значения PAGE_READONLY, PAGE_READWRITE и PAGE_WRITECOPY.

Максимальные размеры проецируемого файла задаются параметрами dwMaximumSizeHigh и dwMaximumSizeLow. Поскольку максимальный размер файла в Windows превышает 232, то это значение разбивается на два 32-х битных значения. Если передать в обеих частях 0, то для создания проекции будет использован текущий размер файла. Однако это может привести к ошибке, если в этот момент сам файл также имеет нулевой размер.

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

Параметр lpName позволяет задать имя для объекта проекция файла.

Функция CreateFileMapping возвращает дескриптор созданного объекта ядра, или значение NULL в случае ошибки.

Как и для всех объектов ядра, у которых есть имя, для проекций файла существует функция, позволяющая открыть уже существующий объект, используя его имя:

HANDLE OpenFileMapping(

DWORD dwDesiredAccess, // access mode

BOOL bInheritHandle, // inherit flag

LPCTSTR lpName // object name

);

Размеры файла в Windows превосходят размер адресного пространства, поэтому, вообще говоря, мы не можем проецировать большие файлы целиком в адресное пространство нашего процесса. Поэтому, после того как мы создали или открыли объект проекция файла, нам необходимо указать, какую часть файла мы хотим отобразить в память. Сделать это можно с помощью вызова MapViewOfFile:

LPVOID MapViewOfFile(

HANDLE hFileMappingObject, // handle to file-mapping object

DWORD dwDesiredAccess, // access mode

DWORD dwFileOffsetHigh, // high-order DWORD of offset

DWORD dwFileOffsetLow, // low-order DWORD of offset

SIZE_T dwNumberOfBytesToMap // number of bytes to map

);

В параметре hFileMappingObject передается дескриптор проекции файла. Флаги dwDesiredAccess определяют запрашиваемые права доступа к проекции файла и, соответственно, к отображенным страницам памяти. Они могут принимать значения FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_ALL_ACCESS и FILE_MAP_COPY. Необходимо заметить, что режим FILE_MAP_WRITE подразумевает кроме записи также и чтение и таким образом ничем не отличается от FILE_MAP_ALL_ACCESS.

Параметры dwFileOffsetHigh и dwFileOffsetLow определяют 64-х битное смещение проецируемой области от начала файла. Это смещение должно быть кратно гранулярности выделения памяти в системе, которую можно узнать с помощью функции GetSystemInfo.

Размер области задается одним 32-х битным числом dwNumberOfBytesToMap. Если передать в этом параметре 0, то будет отображен весь файл.

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

Необходимо отметить, что мы можем многократно вызывать функцию MapViewOfFile для одного и того же объекта проекция файла. Таким образом, мы можем, например, отобразить разные области файла по разным адресам, или получить доступ к файлам, размер которых превышает размер адресного пространства. Можно указывать различные права доступа к памяти при разных обращениях, например для повышения безопасности в критические участки кода мы можем передавать адрес памяти, открытый только для чтения (если конечно этого достаточно для нормальной работы программы). Мы можем также отобразить одну и ту же область файла на разные адреса памяти, при этом Windows обеспечит целостность представления данных по всем адресам (в таком случае разным виртуальным страницам памяти будет соответствовать одна страница физической памяти).

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

BOOL UnmapViewOfFile(

LPCVOID lpBaseAddress // starting address

);

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

BOOL FlushViewOfFile(

LPCVOID lpBaseAddress, // starting address

SIZE_T dwNumberOfBytesToFlush // number of bytes in range

);

Мы можем задать начальный адрес синхронизуемой области в параметре lpBaseAddress и ее размер в dwNumberOfBytesToFlush. Если задать размер равный 0, то будет сброшена вся память проекции, начиная с базового адреса и до конца.

При завершении работы с проекциями файлов не забудьте закрыть объекты ядра проекция файла и файл, используя функцию CloseHandle.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]