Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Виртуальное адресное пространство процесса Лекц...doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
309 Кб
Скачать
☆

Создание (резервирование) региона и передача ему физической памяти

Для создания региона явным образом обычно используется функция VirtualAlloc (вызов ряда Win32 функций, таких, как CreateFileMappingили CreateHeap, также имеет следствием создание региона). В процессе создания региона выделяют два этапа: резервирование региона и передачу ему физической памяти (commit). Оба этапа выполняются в результате вызова VirtualAllocи могут быть объединены. В итоге каждая виртуальная страница может оказаться в одном из трех состояний: свободная (free), зарезервированная (reserve) и переданная (committed)

Резервирование региона - быстрая операция, а в последующей передаче памяти не всегда возникает необходимость; таким образом, двухэтапный процесс выделения позволяет повысить эффективность системы управления памятью.

Резервирование региона предполагает выравнивание начала региона с учетом гранулярности памяти (обычно это 64 Кб). Кроме того, размер региона должен быть кратен объему страницы (4Кб для x86 процессора. Узнать размер страницы можно при помощи функции GetSystemInfo ). В случае успешного резервирования происходит коррекция дерева VAD.

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

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

Прогон программы выделения памяти при помощи функции Virtual Alloc

В программе, листинг которой приведен ниже, осуществляется резервирование региона размером 16 страниц виртуальной памяти и затем передача физической памяти его четвертой страницы. В верхнюю часть переданной памяти записывается строка, которая затем распечатывается. Легко убедиться, что выход за пределы переданной памяти при помощи переменной Shiftприводит к ошибке исполнения. В конце регион освобождается при помощи функции VirtualFree.

#include <windows.h>

#include <stdio.h>

void main(void)

{

PVOID pMem = NULL;

char * String;

char * pMemCommited;

int nPageSize = 4096;

int Shift = 4080;

pMem = VirtualAlloc(0, nPageSize*16, MEM_RESERVE, PAGE_READWRITE);

pMemCommited = (char *)pMem + 3 * nPageSize;

VirtualAlloc((PVOID) pMemCommited, nPageSize, MEM_COMMIT, PAGE_READWRITE);

String = pMemCommited + Shift;

sprintf(String,"Hello, world");

printf("%s\n", String);

VirtualFree(String, 0, MEM_RELEASE);

}

Прогон программы, демонстрирующей выделение больших массивов памяти

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

#include <windows.h>

#include <stdio.h>

void main(void)

{

PVOID pMem = NULL;

int nPageSize = 4096;

long SizeCommit = 0;

int nPages = 200;

SizeCommit = nPages * nPageSize;

getchar();

pMem = VirtualAlloc(0, SizeCommit,

MEM_RESERVE| MEM_COMMIT, PAGE_READWRITE);

if(pMem == NULL) printf("VirtualAlloc Error\n");

getchar();

pMem = VirtualAlloc(0, SizeCommit,

MEM_RESERVE| MEM_COMMIT, PAGE_READWRITE);

if(pMem == NULL) printf("VirtualAlloc Error\n");

getchar();

pMem = VirtualAlloc(0, SizeCommit,

MEM_RESERVE| MEM_COMMIT, PAGE_READWRITE);

if(pMem == NULL) printf("VirtualAlloc Error\n");

getchar();

pMem = VirtualAlloc(0, SizeCommit,

MEM_RESERVE| MEM_COMMIT, PAGE_READWRITE);

if(pMem == NULL) printf("VirtualAlloc Error\n");

getchar();

}

Из текста программы видно, что каждый раз по нажатию клавиши "Enter" процессу передается 200 страниц (819200 байт) виртуальной памяти. Это легко проверить по соответствующему приращению счетчика "Байт виртуальной памяти" (см. рис. 9.5).

Рис. 9.5. Поведение счетчика "Байт виртуальной памяти", выделенной процессу DemoVM.

В качестве самостоятельного упражнения можно рекомендовать прогон данной программы с другими параметрами.