Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АОПИ. Старое / АОПИ. Глава 3. Конспекты (06_06_19).rtf
Скачиваний:
62
Добавлен:
10.09.2019
Размер:
201.15 Кб
Скачать

§1. Адресное пространство Регионы в адресном пространстве

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

Операция выделения региона называется резервированием (reserving). При резервировании система обязательно выравнивает начало региона с учетом так называемой гранулярности выделения памяти (allocation granularity). Последняя величина в принципе зависит от типа процессора, но обычно составляет 64 Кбайта.

Резервируя регион в адресном пространстве, система обеспечивает еще и кратность размера региона размеру страницы. Так называется единица объема памяти, используемая системой при управлении памятью. Как и гранулярность выделения ресурсов, размер страницы зависит от типа процессора. В частности, для процессоров x86 он равен 4 Кбайт.

При этом система автоматически округляет запрашиваемый размер региона до большей кратной величины. Если Вы попытаетесь зарезервировать регион размером 10 Кбайт, система автоматически округлит заданное Вами значение до большей кратной величины. А это значит, что на x86 будет выделен регион размером 12 Кбайт.

Когда зарезервированный регион адресного пространства становится не нужен, его следует вернуть в общие ресурсы системы. Эта операция — освобождение (releasing) региона — осуществляется вызовом функции VirtualFree.

Передача региону физической памяти

Чтобы зарезервированный регион адресного пространства можно было использовать, Вы должны выделить физическую память и спроецировать её на этот регион. Такая операция называется передачей физической памяти (committing physical storage). Чтобы передать физическую память зарезервированному региону, Вы обращаетесь все к той же функции VirtualAlloc.

Функция резервирования и фиксации страниц виртуальной памяти

LPVOID VirtualAlloc(

LPVOID lpAddress,

SIZE_T dwSize,

DWORD flAllocationType,

DWORD flProtect

);

Краткое описание.

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

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

Параметры и описание:

(1) lpAddress определяет адрес памяти, указывающий, где именно система должна зарезервировать адресное пространство. Обычно в этом параметре передают NULL, тем самым сообщая функции VirtualAlloc, что система, ведущая учет свободных областей, должна зарезервировать регион там, где, по ее мнению, будет лучше. Поэтому нет никаких гарантий, что система станет резервировать регионы, начиная с нижних адресов или наоборот, с верхних.

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

Допустим, нужно выделить регион, начиная с «отметки» 50 Мбайт в адресном пространстве процесса. Тогда параметр lpAdress должен быть равен 52 428 800 (50 * 1024 * 1024). Если по этому адресу можно разместить регион требуемого размера, система зарезервирует его и вернет соответствующий адрес. Если же по этому адресу свободного пространства недостаточно или просто нет, система не удовлетворит запрос, и функция VirtualAlloc вернет NULL.

Регионы всегда резервируются с учетом гранулярности выделения памяти. Поэтому, если Вы попытаетесь зарезервировать регион по адресу 19 668 992 (300 x 65 536 + 8192), система округлит этот адрес до ближайшего меньшего числа, кратного 64 Кб, и на самом деле зарезервирует регион по адресу 19 660 800 (300 x 65 536).

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

(2) dwSize указывает размер резервируемого региона в байтах. Поскольку система резервирует регионы только порциями, кратными размеру страницы, используемой данным процессором, то попытка зарезервировать, например, 62 Кбайта даст регион размером 64 Кбайта.

(3) flAllocationType сообщает системе, что именно Вы хотите сделать: зарезервировать регион или передать физическую память. Поэтому, чтобы зарезервировать регион адресного пространства, в этом параметре нужно передать идентификатор MEM_RESERVE.

Если Вы хотите зарезервировать регион и не собираетесь освобождать его в ближайшее время, попробуйте выделить его в диапазоне самых старших — насколько это возможно — адресов. Тогда регион не окажется где-нибудь в середине адресного пространства процесса, что позволит не допустить вполне вероятной фрагментации этого пространства. Чтобы зарезервировать регион по самым старшим адресам, при вызове функции VirtualAlloc в параметре lpAddress передайте NULL, а в параметре flAlloccationType

MEM_RESERVE | MEM_TOP_DOWN.

Для передачи физической памяти вызовите VirtualAlloc, указав в параметре flAllocationType MEM_COMMIT.

(4) flProtect указывает атрибут защиты, присваиваемый региону. Заметьте, что атрибут защиты, связанный с регионом, не влияет на переданную память, отображаемую на этот регион. Но если ему не передана физическая память, то — какой бы атрибут защиты у него ни был — любая попытка обращения по одному из адресов в этом диапазоне приведет к нарушению доступа для данного потока. Возможные значения:

PAGE_NO_ACCESS — запрет чтения, записи и исполнения содержимого памяти на данной странице.

PAGE_READONLY — запрет записи и исполнения содержимого памяти на этой странице.

PAGE_READWRITE — запрет исполнения содержимого памяти на этой странице.

PAGE_EXECUTE — запрет чтения и записи на этой странице.

PAGE_EXECUTE_READWRITE — нет запретов.

Возвращаемое значение:

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

Когда физическая память, переданная зарезервированному региону, становится не нужна, её освобождают.