Архитектура API управления памятью.

 

 

Адресное пространство процесса:

Средства защиты памяти:

Объектно-ориентированная защита памяти. Каждый раз, когда процесс открывает указатель на блок адресов, монитор ссылок безопасности проверяет, разрешен ли доступ процесса к данному объекту.

Отдельное адресное пространство для каждого процесса. Аппаратура запрещает процессу доступ к физическим адресам другого процесса.

Два режима работы: режим ядра, в котором процессам разрешен доступ к системным данным, и пользовательский режим, в котором это запрещен.

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

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

 

Страничное преобразование:

Виртуальная память в Windows имеет страничную организацию, принятую во многих современных ОС. Процессоры Intel начиная с Pentium Pro позволяют ОС применять одно-, двух- и трехступенчатые схемы. И даже разрешается одновременное использование страниц различного размера. Эта возможность, конечно, повысила бы эффективность страничного преобразования, будь она внедрена в Windows. Однако Windows возникла раньше и поддерживает только двухступенчатую схему преобразования с фиксированным размером страниц.

Каждому процессу назначается свой каталог страниц. Именно поэтому адресное пространство каждого процесса изолировано, что очень хорошо с точки зрения защиты процессов друг от друга.

32-разрядный виртуальный адрес в ОС Windows разбивается на три части:

Старшие 10 разрядов адреса определяют номер одного из 1024 элементов в каталоге страниц, адрес которого находится в регистре процессора CR3. Этот элемент содержит физический адрес таблицы страниц.

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

Размер страницы - 4 Кбайт, и младших 12 разрядов линейного адреса как раз хватает (212 = 4096), чтобы определить точный физический номер адресуемой ячейки памяти внутри этой страницы.

 

 

 
 

 

 


Защита – Win32 API поддерживает ряд значений, в том числе: PAGE_NOACCESS, PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE.

Базовый физический адрес страницы в памяти.

Pagefile – индекс используемого файла подкачки (один из 16 возможных в системе файлов).

State – состояние страницы в системе:

1. T (Transition) – отмечает страницу как переходную;

2. D (Dirty) – страница, в которую была произведена запись;

3. P (Present) – страница присутствует в ОП или находится в файле подкачки.

 

Отдельные состояния страниц:

Valid – страница используется процессом. Она реально существует в ОП и помечена в PTE как присутствующая в рабочем множестве процесса (P=1, D=0,1).

Modified – содержимое страницы было изменено (D=1). В PTE страница помечена как отсутствующая (P=0) и переходная (T=1).

Standby – содержимое страницы не изменялось (D=0). В PTE страница помечена как отсутствующая (P=0) и переходная (T=1).

Free – страница, на которую не ссылается ни один PTE. Страница свободна, но подлежит обнулению, прежде чем будет использована.

Zeroed – свободная и обнуленная страница, пригодная к непосредственному использованию любым процессом.

Bad – страница, которая вызывает аппаратные ошибки и не может быть использована ни одним процессом.

 

T D P Page state
- Invalid page (Free)
- Valid page
- Valid dirty page
Invalid page in transition (Standby)
Invalid dirty page in transition (Modified)

 

Реализация свопинга:

 

11. Архитектура памяти 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. текущее и пиковое использование файла подкачки.

 

12. Архитектура памяти в MS Windows 200-2003. Организация «динамической» виртуальной памяти. Назначение и преимущество по сравнению с кучами ANSI C. Функции Win32 API.

Кучи (heaps) – это динамически распределяемые области данных.

При порождении процесса ему предоставляется куча размером 1 Мбайт по умолчанию. Ее размер может изменяться параметром /HEAP при построении исполняемого модуля.

Функции библиотеки времени исполнения компилятора CRT (malloc(), free() и т. д.) используют возможности куч.

Создание дополнительных «куч»:

- для повышения эффективности управления памятью;

- для уменьшения рабочего множества процесса ;

- для повышения эффективности работы многонитевых приложений;

- для “защиты” друг от друга различных структур данных;

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

 

Повышение эффективности управления памятью:

В системах со страничной организацией отсутствует проблема фрагментации физической памяти. Однако существует проблема фрагментации адресного пространства. В 4Gb адресном пространстве эта проблема не актуальна, но она имеет значение в 1Mb куче.

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

Уменьшение рабочего множества процесса:

В соответствии с принципом локальности, работа с разными структурами, чаще всего, происходит не одновременно. Границы элементов разных структур не выровнены на границу страницы.

Обращение к элементам одной структуры вызывает подкачку всей страницы, а, значит и элементов другой структуры. Это увеличивает рабочее множество процесса.

Функции создания и использования «куч»:

HANDLE GetProcessHeap (VOID ) – для получения дескриптора кучи по умолчанию;

LPVOID HeapAlloc (HANDLE hHeap, DWORD dwFlags, DWORD dwSize) – для выделения из кучи блока памяти заданного размера и возвращения указателя;

LPVOID HeapReAlloc (HANDLE hHeap, DWORD dwFlags, LPVOID lpOldBlock, DWORD dwSize) – для изменения размера выделенного блока памяти с возможностью перемещения блока при необходимости;

BOOL HeapFree (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) – для освобождения выделенного блока памяти кучи.

 

Создание и уничтожение «кучи»:

 

HANDLE HeapCreate (

DWORD dwFlags,

DWORD dwInitialSize,

DWORD dwMaximumSize

);

BOOL HeapDestroy ( HANDLE hHeap);

 

Создание «кучи» - dwFlags:

HEAP_GENERATE_EXCEPTIONS – указывает системе на то, что в случае возникновения ошибки необходимо генерировать исключительную ситуацию. Это будет происходить во всех случаях, когда функция должна была бы возвратить значение null.

HEAP_NO_SERIALIZE – указывает, что пока выполняется текущий вызов HeapAlloc, к куче не будут происходить обращения из других потоков (т.е. программист сам берет на себя исключение ситуаций одновременных обращений).

HEAP_ZERO_MEMORY – указывает, что выделяемая память должна инициализироваться нулями. В противном случае память не обязательно инициализируется нулями.

Дополнительные возможности по управлению «кучами»:

UINT HeapCompact (HANDLE hHeap, DWORD fdwFlags);

BOOL HeapLock (HANDLE hHeap);

BOOL HeapUnlock (HANDLE hHeap);

BOOL HeapWalk (HANDLE hHeap, PPROCESS_HEAP_ENTRY pHeapEntry);