- Статьи для начинающих -

   
- Назад на оглавление -
Руководство по распределению памяти

Однажды на просторах сети наткнулся я на интересную разработку - Moebius OS Тима Робинсона - www.themoebius.org.uk Помимо собственно ОС, автор написал несколько руководств, отлично разъясняющих принципы разработки ОС. Прочитав их, я просто не мог не донести до вас переводы этих туториалов :) Структура была немного изменена, ценителей же призываю обратиться к оригиналу, расположенному на вышеозначенном сайте :)

Lonesome

Введение

Это руководство было написано для того, чтобы помочь вам разработать менеджер памяти для вашей собственной системы. Я предполагаю, что вы решили попытаться разработать свою ОС и она уже умеет больше чем просто загрузиться и вывести 'Hello World'. Поздравляю, вы зашли дальше чем большинство разработчиков ОС.

Менеджер памяти - один из низкоуровневых компонентов любой операционной системы - жизненной важный компонент, необходимый для разделения памяти компьютера. Примечание: в ядре ОС может быть несколько менеджеров памяти, каждый их которых работающих на различных уровнях, но я расскажу лишь про менеджер памяти самого низкого уровня

Я не собираюсь рассказывать, что в точности вы должны сделать, но вместо этого дам несколько примеров. Вы можете использовать их, но помните, что разные ОС выполняют свои функции по разному. И поскольку вы пишете собственную ОС, вероятно вы хотите, чтобы она отличалась от существующих и не намерены просто копировать нечто уже написанное.

Предполагается что ядро системы выполняется в режиме супервизора на некоторой защищенной архитектуре. В случае архитектуры x86 это означает, что оно выполняется с уровнем привилегий 0 в защищенном режиме. Наличие процессора x86 не предполагается, но но примеры кода я буду давать для него. Также эти примеры будут на языке Си. Вы можете писать систему на ассемблере или паскале (это возможно?), но я убежден, что Си - хороший полу-универсальный язык для разработки ОС. Кроме того свою систему я тоже разрабатываю на Си.

Возможно вам покажется, что в этом руководстве слишком много "воды", но вместо того, чтобы учить вас что делать(вокруг полно таких руководств и даже примерных ОС), я расскажу почему вы делаете это именно так Надеюсь что кому нибудь это сослужит пользу.

Спецификации

Низкоуровневый менеджер памяти достаточно прост. После того как загрузчик передал управление ядру системы, мы получили полный контроль над аппаратной частью компьютера. Ядро системы выполняется в некоторый части памяти, в которую оно было помещено загрузчиком. Также настроен стек. Короче говоря, все настроено для того, чтобы ядро могло вывести сообщение и зависнуть.

Менеджер физической памяти должен быть одним из первых запущенных компонентов системы (разумеется самым первым должен быть код, выводящий ваше имя на экран). Конечно если ваше ядро уже может использовать глобальные переменные (настроена область данных), вызывать функции (настроен стек) и выводить данные на экран (настроен доступ к остальной памяти), то вас может обуять желание кое-как побыстрее написать примитивный менеджер памяти, затем переключиться в графический режим и разработать GUI. Такой вариант развития событий также возможен (такова была философия Windows до 1995 года), но дальнейшее развитие системы может быть затруднено как только вы попытаетесь разрабатывать нечто более серьезное (с этой проблемой столкнулись Windows9x)

Задача менеджера физической памяти достаточно проста - разделить физическое адресное пространство на куски подходящего размера и распределить их между частями системы, которым они нужны. Для простоты мы будем называть эти куски страницами. На x86 размер страницы по умолчанию равен 4кб.

Архитектура x86 достаточно уникальна поскольку на ней поддерживаются как сегменты, так и страницы. Обращение к памяти идет через сегменты, после чего адрес претерпевает страничное преобразование. В использовании страничной адресации есть преимущества:

  • Большинство других 32-битных архитектур разделяют 4-х гигабайтное адресное пространство на страницы как и 386. x86 вводит сегментацию, что позволяет ОС обращаться к памяти как к коду, данным, стеку , и.т.п., - в этом отличие x86 от большинства других процессоров. Портировать ОС использующую сегменты на другие архитектуры практически невозможно. Также ни один из известных компиляторов не поддерживает сегментацию в 32-битном режиме, по этому при разработке под эту ОС вы ограничены ассемблером

Итак, наш менеджер памяти будет работать со страничным распределением. Теперь наша цель - избавиться от жесткой физической адресации во всех частях системы кроме самого менеджера памяти, что позволит системе не зависеть от количества памяти и метода ее распределения. Например процессоры Pentium и выше поддерживают 4-мб страницы, что вкупе с 36-битным физическим адресным пространством дает вам 64гб. (виртуальное адресное пространство по прежнему ограничено 4-мя гб). При правильно спроектированной системе, менеджер памяти - единственная ее часть которая потребует изменения при портировании на такую архитектуру.

Организация

Для безопасного выполнения пользовательских приложений, память должна быть разделена на системную (ядро и драйвера) и пользовательскую часть. Ядро не должно быть доступно для пользовательских приложений. Многие ОС (Win9x, NT и Linux к примеру) разделяют 4-х гигабайтное адресное пространство на две части по 2 гб. и выделяют нижнюю часть для пользовательских приложений. Как это сделать, если ядро, допустим, на самом деле загружено по адресу 1мб? Страничная адресация позволяет без труда добиться нужного эффекта - просто укажите в таблице страниц нужные физические адреса.

Для простоты мы будем выделять пространство только 4кб страницами. Поскольку низкоуровневый менеджер памяти должен знать только выделена ли страница или нет, то на каждую из них достаточно иметь один бит. При 256мб памяти, нам потребуется всего лишь 8кб памяти для управления всеми 65536 страницами. Преимущества такого "битового" подхода - простота и экономичность. Тем не менее при выделении страницы мы должны производить поиск по всей битовой карте.
Альтернативный способ - использование стека страниц. Физические адреса свободных страниц кладутся на вершину стека. Когда страница выделяется, ее адрес берется из стека, когда освобождается - кладется обратно. Этот метод не требует поиска. Но он не способен обеспечить выделение последовательных участков памяти. Например ISA DMA требует адреса находящегося в пределах первых 16мб (из-за 24-битной адресной шины). В случае стека страниц наиболее простым решением было бы держать два стека - один для памяти ниже 16 мб, другой - для остальной.

Инициализация

Прежде всего мы должны выделить память для управляющих структур - будь то битовая карта или стек(и) страниц. Количество памяти для них пропорциально объему физической памяти в системе. Лучший способ определить его - использовать прерывание 15h BIOS до перехода в защищенный режим

Теперь мы знаем, сколько памяти мы имеем и пришло время выделить память для самого менеджера. Для этого мы должны зарезервировать некоторое количество памяти, которая не будет использоваться при распределении. Кроме того необходимо зарезервивать область памяти BIOS, BDA, самого ядра и пр (пометить эту память в управляющих структурах как выделенную)

Выделение

Первая функция нашего менеджера памяти - выделение страницы - менеджер должен пометить страницу как занятую и возвратить ее адрес.

Но что делать, если свободных страниц не осталось? Если бы у нас была система свопинга, то мы должны бы были выгрузить неиспользуемые страницы на диск и пометить их свободными. Но чтобы сделать это, потребуется намного больше работы - как минимум драйвер доступа к диску, так что сейчас достаточно возвратить результат, что память отсутствует

Освобождение

Освобождение памяти - процесс обратный выделению. Просто пометьте адрес страницы как свободный

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

Tim Robinson бT timothy.robinson@ic.ac.uk бT http://www.themoebius.org.uk/

Хостинг от uCoz