- •Введение
- •Связывание адресов
- •Общее описание виртуальной сегментно-страничной памяти ос Windows
- •Инструментальные средства наблюдения за работой менеджера памяти
- •Виртуальное адресное пространство процесса
- •Регионы в виртуальном адресном пространстве
- •Создание (резервирование) региона и передача ему физической памяти
- •Прогон программы выделения памяти при помощи функции Virtual Alloc
- •Прогон программы, демонстрирующей выделение больших массивов памяти
- •Регион куча
- •Прогон программы выделения памяти в стандартной куче
- •Регион стека потока. Сторожевые страницы
- •Прогон программы, моделирующей обращение к сторожевым страницам
- •Регион файла, отображаемого в память
- •Прогон программы, демонстрирующей отображение файла в память
- •Написание, компиляция и прогон программы, демонстрирующей различные аспекты проецирования файла в память
- •Заключение
Регион куча
Как уже говорилось, в ряде случаев система сама резервирует регионы в адресном пространстве процесса. Примерами таких регионов могут служить регион куча и регион стека потока.
Куча (heap) - зарезервированный регион размером в одну и более страниц, который рекомендуется использовать для хранения множества небольших порций данных. В отличие от функции VirtualAllocправила гранулярности выделения памяти при этом соблюдать не обязательно.
Передачей памяти кучам, а также учетом свободной и занятой памяти в куче занимается специальный диспетчер куч (heap manager). Эта деятельность не документирована.
Стандартная куча процесса размером 1 Мб (эту величину можно изменить) резервируется в момент создания процесса. Обычно куча динамически меняет свой размер (флаг growable ). Стандартную кучу процесса используют не только приложения, но и некоторые Win32-функции. Для использования стандартной кучи необходимо получить ее описатель при помощи функции GetProcessHeap.
При желании процесс может создать дополнительные кучи при помощи функции HeapCreate (обратная операция HeapDestroy ). Прикладная программа выделяет память в куче с помощью функции HeapAlloc, а освобождает при помощи HeapFree.
Поскольку кучами могут пользоваться все потоки процесса, по умолчанию организуется синхронизация (флаг SERIALIZE ), которую, хотя это и не рекомендуется, для повышения быстродействия можно отменить. Задачу синхронизации доступа потоков к куче можно также решить, создавая каждому потоку свою собственную кучу.
Прогон программы выделения памяти в стандартной куче
#include <windows.h>
#include <stdio.h>
void main(void)
{
HANDLE hHeap;
long Size = 1024;
long Shift = 1017;
char * pHeap;
char * String;
hHeap = GetProcessHeap();
pHeap = (char *) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, Size);
if(pHeap == NULL) { printf("HeapAlloc error\n"); return; }
String = pHeap + Shift;
sprintf(String, "Hello, world");
printf("Heap contents string: %s\n", String);
HeapFree(hHeap,0,pHeap);
}
В приведенной программе происходит выделение массива памяти в стандартной куче процесса.Далее туда записывается текстовая строка, которая затем выводится на экран. Если возникает ситуация выхода за пределы выделенной памяти, которую легко смоделировать, увеличивая значение параметра Shift, - возникает ошибка исполнения.
В качестве самостоятельного упражнения можно рекомендовать наблюдение за наращиванием объема переданной в куче памяти при помощи счетчиков производительности. Объем виртуальной памяти процесса должен начать расти в случае выхода за пределы начального размера кучи (1 Мб) и при образовании дополнительных куч.
Регион стека потока. Сторожевые страницы
Для поддержки функционирования стека потока также резервируется соответствующий регион. Стек - динамическая структура. Принято, чтобы стек увеличивал свой размер в сторону уменьшения адресов. Сколько страниц памяти потребуется стеку потока, заранее не известно. Поэтому в ОС Windows организована поэтапная, по мере необходимости, передача физической памяти стеку при помощи механизма так называемых "сторожевых" страниц (guard page). Обращение к сторожевой странице имеет следствием уведомление системы об этом (исключительная ситуация 0x80000001 ), после чего флаг PAGE GUARDсбрасывается и со страницей можно работать как с обычной страницей преданной памяти. Сторожевая страница служит ловушкой для перехвата ссылок за ее пределы.
При создании потока для его стека резервируется регион размером 1 Мб (по умолчанию), и ему передается 2 страницы памяти (эти параметры могут быть изменены). Нижняя страница является сторожевой. Как только верхняя страница оказалась заполненной и произошло обращение к нижней странице, это замечается системой и региону передается еще одна страница, теперь уже она становится сторожевой. Вследствие такой тактики самая нижняя переданная региону стека страница всегда остается сторожевой и ее задача - просигнализировать системе о том, что объем переданной стеку памяти нужно увеличить.
