Управление памятью в операционной системе WINDOWS, страница 3

MMU может пометить страницу виртуальной памяти как отсутствующую (absent). Этот механизм лежит в основе организации виртуальной памяти. MMU сообщает операционной системе, что произошло обращение к отсутствующей в физической оперативной памяти странице. ОС загружает отсутствующую страницу в физическую память и разрешает программе вновь попробовать обратиться к ней. Конечно же, чтобы освободить место для загрузки отсутствующей страницы, ОС может записать на диск какую-либо другую страницу виртуальной памяти и пометить ее как отсутствующую.

Механизм отсутствующих страниц используется также для организации разреженных массивов (sparsearrays). Представьте, что вы работаете с очень большой матрицей вещественных чисел, для хранения которой необходимо выделить 10 Мбайт оперативной памяти. Допустим также, что большая часть элементов матрицы равна нулю (или любому другому константному значению). Матрицы такого рода очень часто используются при решении разного сорта инженерных задач.

Неужели нет никакого другого способа хранения такой матрицы, кроме как выделить память для того, чтобы записать в нее 10 Мбайт нулей? Windows предлагает следующее решение проблемы. Вся матрица разделяется на страницы по 4 Кбайта. Если страница содержит нули, она помечается как отсутствующая, Когда программа, работающая с матрицей, обращается к такой странице, MMU'сообщает ей, что страница отсутствует, и программа понимает, что все ячейки страницы на самом деле равны нулю, Таким образом, на хранение страниц, целиком заполненных нулями, драгоценная физическая память не расходуется.

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

В качестве аргументов функция принимает адрес области памяти, ее размер, режим выделения и уровень защиты, Если в качестве первого аргумента функции передать значение NULL, операционная система самостоятельно определит подходящий адрес выделяемой области. Вместо этого вы можете попросить ее выделить память с конкретным начальным адресом (этот адрес должен соответствовать границе страницы). Второй аргумент — количество байт, которое необходимо выделить. Windows автоматически округлит это количество таким образом, чтобы оно равнялось числу, кратному размеру страницы. Если вы хотите просто выделить память, в качестве третьего аргумента необходимо указать значение МЕМ_СОММ1Т, Последний аргумент — уровень защиты, который будет соответствовать выделяемой памяти (табл.1). Очевидно, что использовать некоторые из перечисленных здесь атрибутов (например, PAGE_READONLY) не имеет смысла, так как память не инициализирована начальными значениями,

Константы уровня защиты                                                                    Таблица 7.1.

Флаг

Значение

PAGE_READONLY

Выделяется память только для чтения.

PAGE_READWRITE

Выделяется память, как для чтения, так и для записи.

PAGE_WRITECOPY

После осуществления записи страница заменяется ее новой копией (используется совместно с общей памятью или отраженными на память файлами)

PAGE_EXECUTE

Разрешается исполнение программного кода, расположенного в выделяемой памяти.

PAGE_EXECUTEREAD

Разрешается исполнение программного кода и чтение данных, расположенных в выделяемой памяти.

PAGE_EXECUTEREADW

Разрешается исполнение программного кода, а также чтение и запись данных, расположенных в выделяемой памяти.

PAGE_PAGENOACCESS

Запрещает любой доступ к выделенной памяти. В случае любого доступа возникает ошибка General Protection Fault (GPF).

PAGE_GUARD

Страницы в выделяемой памяти становятся «сторожевыми». При попытке осуществить чтение или запись данных в сторожевой странице операционная система инициирует исключение STATUS_GUARD_PAGE и сбрасывает статус сторожевой страницы. Таким образом, сторожевые страницы работают в режиме «тревога-при-первом-обращении». Обычно такой режим используется совместно с другими флагами (за исключением флага PAGE_NOACCESS)

PAGE_NOCACHE

Запрещает кэширование страниц (не рекомендуется). Используется совместно с другими флагами (за исключением флага PAGE_NOACCESS)