Архитектура памяти MS Windows 2000-2003. Организация «статической» виртуальной памяти. Блоки адресов. Состояния блоков адресов. Функции Win32 API.
Работа приложений с виртуальной памятью:
Резервирование и выделение памяти производится блоками адресов.
Начальный адрес блока должен быть выровнен на границу 64K (округляется вниз), а размер кратен размеру страницы (округляется вверх). При выделении память обнуляется.
Блок адресов в адресном пространстве процесса может находиться в одном из трех состояний:
1. Выделен (committed) – блоку адресов назначена физическая память либо часть файла подкачки.
2. Зарезервирован (reserved) – блок адресов помечен как занятый, но физическая память не распределена.
3. Свободен (free) – блок адресов не выделен и не зарезервирован.
Функции API для работы виртуальной памятью:
Для резервирования региона памяти в адресном пространстве процесса или выделения ее используется функция VirtualAlloc, а для освобождения – функция VirtualFree. Для работы в адресном пространстве произвольного процесса необходимо использовать функции VirtualAllocEx и VirtualFreeEx.
Выделенные страницы можно заблокировать в памяти, т.е. запретить их вытеснение в файл подкачки. Для этих целей служит пара функций VirtualLock и VirtualUnlock. Процессу не разрешается блокировать более 30 страниц.
Для изменения атрибутов защиты регионов используются функции VirtualProtect и VirtualProtectEx. Причем, первая позволяет изменять атрибуты защиты в адресном пространстве текущего процесса, а вторая – произвольного.
LPVOID VirtualAlloc (
LPVOID lpAddress, // адрес, по которому надо зарезервировать
// или выделить память
DWORD dwSize, // размер выделяемого региона
DWORD flAllocationType, // тип распределения памяти
DWORD flProtect // тип защиты доступа
);
LPVOID VirtualAllocEx (
HANDLE hProcess, // дескриптор процесса
LPVOID lpAddress, // адрес, по которому надо зарезервировать
// или выделить память
DWORD dwSize, // размер выделяемого региона
DWORD flAllocationType, // тип распределения памяти
DWORD flProtect // тип защиты доступа
);
Функции API для работы с ВП: VirtualAlloc
Параметр flAllocationType может принимать следующие значения:
1. MEM_RESERVE - резервирует блок адресов без выделения памяти;
2. MEM_COMMIT - отображает ранее зарезервированный блок адресов на физическую память или файл подкачки, выделяя при этом память. Может комбинироваться с флагом MEM_RESERVE для одновременного резервирования и выделения;
3. MEM_TOP_DOWN - выделяет память по наибольшему возможному адресу. Имеет смысл только при lpAddress = NULL. В Windows 95 игнорируется.
4. MEM_DECOMMIT - освободить выделенную память;
5. MEM_RELEASE - освободить зарезервированный регион. При использовании этого флага параметр dwSize должен быть равен нулю.
Параметр flProtect - тип защиты доступа выделяемого региона:
1. PAGE_READONLY - допускается только чтение;
2. PAGE_READWRITE - допускается чтение и запись;
3. PAGE_EXECUTE - допускается только выполнение;
4. PAGE_EXECUTE_READ - допускается исполнение и чтение;
5. PAGE_EXECUTE_READWRITE - допускается выполнение, чтение и запись;
6. PAGE_GUARD - дополнительный флаг защиты, который комбинируется с другими флагами. При первом обращении к странице этот флаг сбрасывается и возникает исключение STATUS_GUARD_PAGE. Этот флаг используется для контроля размеров стека с возможностью его динамического расширения;
7. PAGE_NOCACHE - запрещает кэширование страниц. Может быть полезен при разработке драйверов устройств (например, данные в видеобуфер должны переписываться сразу, без кэширования).
BOOL VirtualFree (
LPVOID lpAddress, // адрес региона, который надо освободить
DWORD dwSize, // размер освобождаемого региона
DWORD dwFreeType // тип освобождения
);
dwSize – размер, если мы будем использовать тип освобождения, как MEM_RELEASE, то размер должен быть установлен в 0.
dwFreeType – будет определять какая операция произойдет с памятью:
1. MEM_RELEASE – освобождена;
2. MEM_DECOMMIT – зарезервирована, но не используется.
При успешном выполнении функция вернет TRUE в случае успеха и FALSE - в случае неудачи.
BOOL VirtualFreeEx (
HANDLE hProcess, // дескриптор процесса
LPVOID lpAddress, // адрес региона, который надо освободить
DWORD dwSize, // размер освобождаемого региона
DWORD dwFreeType // тип освобождения
);
Для изменения атрибутов защиты регионов используются функции VirtualProtect и VirtualProtectEx.
VirtualProtect позволяет изменять атрибуты защиты в адресном пространстве текущего процесса.
VirtualProtectEx позволяет изменять атрибуты защиты в адресном пространстве произвольного процесса.
BOOL VirtualProtect (
LPVOID lpAddress, // адрес региона для установки флага
DWORD dwSize, // размер региона
DWORD flNewProtect, // флаг
PDWORD lpflOldProtect // адрес для сохранения старых флагов
);
Функция VirtualLock() позволят предотвратить запись памяти на диск.
BOOL VirtualLock (
LPVOID lpAddress, // адрес начала памяти
SIZE_T dwSize // количество байтов
);
Если фиксация больше не нужна, то ее можно убрать функцией VirtualUnlock().
BOOL VirtualUnlock (
LPVOID lpAddress, // адрес начала памяти
SIZE_T dwSize // количество байтов
);
При успешном выполнении обе функции возвращают ненулевое значение.
Функции VirtualQueryи VirtualQueryEx позволяют определить статус указанного региона адресов.
Процессу не разрешается блокировать более 30 страниц.
Для настройки рабочего множества процесса может использоваться и функция SetProcessWorkingSetSize, которая может снять это ограничение.
SetProcessWorkingSetSize позволяет задать для процесса минимальный и максимальный размер рабочего множества процесса.
BOOL SetProcessWorkingSetSize (
HANDLE hProcess, // дескриптор процесса
DWORD dwMinimumWorkingSetSize, // мин. размер рабочего мн-ва процесса, в байтах
DWORD dwMaximumWorkingSetSize // макс. размер рабочего мн-ва процесса, в байтах
);
Если и dwMinimumWorkingSetSize и dwMaximumWorkingSetSize имеют значение –(минус) 1, функция временно урезает рабочее множество процесса до нуля. Это, по существу, выносит процесс за пределы физической оперативной памяти.
Аналогичный результат достигается с помощью функции EmptyWorkingSet.
Дескриптор процесса должен иметь права доступа PROCESS_SET_QUOTA.
Если значения dwMinimumWorkingSetSize или dwMaximumWorkingSetSize больше, чем текущий размер рабочего множества памяти процесса, данный процесс должен иметь привилегию SE_INC_BASE_PRIORITY_NAME.
Получение справочной информации по ВП процесса:
GetProcessWorkingSetSize – получение текущих значений минимального и максимального размера рабочего множества процесса.
GetProcessMemoryInfo – получение расширенной статистики по использованию ВП процесса, например:
1. количество страничных прерываний;
2. текущий и пиковый размер рабочего множества процесса;
3. текущее и пиковое использование файла подкачки.