- •Лекция №4. Архитектура памяти. Управление памятью. Mdl. Выделение памяти. Отображение памяти. [4.1] Организация памяти в защищенном режиме работы процессора
- •[4.2] Организация системного адресного пространства
- •[4.4] Совместное использование памяти
- •[4.5] Объект Секция
- •[4.6] Таблица описания памяти (Memory Descriptor List - mdl)
- •[4.7] Подведение итогов. Функции работы с памятью
- •[4.7.1]Выделениепамяти
- •[4.7.2] Lookaside List
- •[4.7.3] Отображение памяти устройств и пространства в/в
- •[4.7.4]УправлениепамятьюиMdl
[4.2] Организация системного адресного пространства
Как уже отмечалось, системное адресное пространство сильно отличается от пользовательского:
системное адресное пространство одинаково вне зависимости от текущего контекста памяти, т.е. от содержимого пользовательского адресного пространства.
В системном адресном пространстве имеются диапазоны памяти как выгружаемые на диск, так и не выгружаемые.
На следующем рисунке показана приблизительная организация системного адресного пространства для платформы x86.
Рис. 2
Как мы уже отмечали, линейный и виртуальный адреса в NT совпадают. Здесь и далее мы будем пользоваться термином виртуальный адрес.
Виртуальный адрес транслируется в физический адрес. Этот адрес соответствует физической памяти.
Кроме этих двух типов адресов существует еще один – логический адрес, реализуемый на уровне HAL.
HAL поддерживает гибкую модель для адресации аппаратных устройств. В соответствии с этой моделью, устройства подключаются к шинам, каждая из которых имеет свое собственное адресное пространство. Реально эти адреса могут быть как в пространстве портов в/в, так и в пространстве памяти.
Прежде чем может быть произведено обращение к некоторому адресу устройства (посредством функции HAL), адрес должен быть переведен из относительного адреса для шины в некоторый транслированный модулем HAL адрес. Этот транслированный адрес и есть логический адрес. Он имеет смысл только для HAL и не имеет ничего общего с конкретным адресом для работы с оборудованием.
Для получения логического адреса из шинного адреса служит функция HalTranslateBusAddress(). Полученный адрес будет находиться либо в пространстве портов в/в, либо в обычном пространстве памяти. В последнем случае для использования в драйвере полученный логический адрес должен быть преобразован к адресу в невыгружаемой области системного адресного пространства. Это делается посредством вызова функции MmMapIoSpace().
[4.4] Совместное использование памяти
Рис. 3

Из рис.3 видно, что разные таблицы страниц могут иметь ссылку на одну и ту же физическую страницу памяти. Эта возможность позволяет приложениям совместно использовать одну и ту же физическую память (обращаясь при этом к различным виртуальным адресам).
Кроме того, как уже говорилось выше, на уровне таблиц страниц производится управление доступом к страницам памяти. При этом к одной и той же физической странице памяти может быть предоставлен различный уровень доступа даже внутри одного адресного пространства (никто не запрещает нескольким элементам одной таблицы страниц указывать на одну физическую страницу).
Для совместно используемой памяти может быть задействован механизм Copy-On-Write. В элементе таблицы страниц для такой памяти сброшен бит доступа на запись, и установлен специальный бит задействования режима Copy-On-Write. Пока два процесса совместно используют такую память для чтения, ничего не происходит. При попытке записи одним из процессов в такую память генерируется исключение (защита от записи). Диспетчер памяти анализирует исключение, обнаруживает, что для страницы установлен механизм Copy-On-Write, создает новую страницу в физической памяти, копирует в нее первоначальную страницу и модифицирует элемент таблицы страниц так, чтобы он указывал на новую страницу, а затем производит первоначальную запись в память. Таким образом, каждый процесс получит свою копию первоначальной страницы каждый со своими изменениями.
Все исполняемые модули в ОС NT находятся в совместно используемой памяти с задействованием Copy-On-Write. Это означает, например, что при отладке кода DLL, используемой в некотором процессе, при установке точки прерывания (что осуществляется записью в код), она будет присутствовать только в этом адресном пространстве.
Для постановки точки прерывания на код в DLL так, чтобы она срабатывала вне зависимости от адресного пространства, необходимо предпринять специальные действия:
Для данного виртуального адреса нужно получить физический адрес
Для физического адреса создать новую запись в таблице страниц, устанавливающих для страницы доступ на запись. Создание записи в таблице страниц означает получение нового виртуального адреса.
При записи по полученному виртуальному адресу будет модифицирована страница физической памяти, соответственно это изменение увидится во всех контекстах памяти, на которые отображена эта страница.
Естественно, первые два шага можно сделать только в коде режима ядра, т.е. из драйвера.
