Rambler's
Top100

Разработка операционных систем. Выпуск 18

Автор: lonesome [TSH/Digital Daemons]
Дата: 26.07.2003
Раздел: Разработка ОС

ПРЕДЫДУЩИЙ ВЫПУСК      СЛЕДУЮЩИЙ ВЫПУСК

Разработка операционных систем

Выпуск 18 от 2003-06-27

Сегодня в номере:

Intro

Здравствуйте, уважаемые подписчики. Вот вам сперва отличная идея от Havoc
(напоминаю, если есть какие-то комментарии, то добро пожаловать в наш форум:
http://www.lowlevel.ru/cgi-bin/yabb/YaBB.cgi?board=programming.)
> 
> Предлагаю (для многозадачных систем) ввести три уровня "привилегий",
> устанавливаемых пользователем:
> 1) обычный режим
> 2) сингл-режим
> 3) защищенный режим
> 
> В обычном режиме все программы работают с приоритетом супервизора, ОС
> используется только как инструмент(!) для распределения ресурсов, и
> программно-аппаратных абстракций, т.е. программа может пользоватся
> механизмами ОС, но всегда может напрямую работать с ресурсами.
> 
> В сингл-режиме все ресурсы отдаются программе, все остальные программы
> касулируются в памяти (или лучше выгружаются из нее, с последующим
> перезапуском), рабочими остаются только механизмы аппаратных
> абстракций (которые, опять-же, могут не использываться).
> 
> Ну и в защищенном режиме программа вынуждена работать только с
> механизмами ОС, причем без каких либо исключений. Программа жестко
> капсулируется в памяти, не знает о том, что существуют другие
> программы и какие-либо устройства, пока ОС ей об этом не скажет
> (опять-же должна быть возможность настраивать о чем должна знать
> программа, а о чем нет).
> В случае если программу написанную специально для сингл-режима нужно
> запустить взащищенном, то запускается "виртуальная машина" (эмулятор
> синглрежима).
> 
> Насчет механизма абстракций:
> В ОС изначально их быть не должно вообще(за исключением базовой
> поддержки ввода-вывода(консоль)) все остальные мех. абстракции должны
> устанавливатьсяотделно пользователем в виде модулей, или они могут
> быть реализованына базе драйверов(при установке драйвера, он ставит
> под себя системуинтерфейсов, единую для данного класса устройств).
> 
> Насчет Плуг&Плей:
> ОС не должна знать какое железо стоит, Все определяется опять-же
> драйвером: есть драйвер - есть устройство, нет драйвера - нет и
> устройства(для ОС, программы в базовом и сингл режимах могут знать и
> работать с неизвестными для ОС уст-вами напрямую).
> Исключение должны составлять только видео, клавиатура, HDD, FDD и,
> можетбыть, CD-ROM. Для видео должен использываться базовый драевер,
> предназначеный только для вывода на консоль. А также должен быть
> модуль, который бы сам определял PnP уст-ва, т.е. нужно
> автоопределение - устан. модуль, не нужно - не устан.
> 
> 

Виртуальная память

Механизмы виртуальной памяти - одна из важнейших составляющих современной операционной системы. Что они из себя представляют? В общем случае механизмы виртуальной памяти позволяют эмулировать обращение к определенной ячейке памяти, причем эмуляция может осуществляться разными способами, наиболее часто используемый из которых - обычное отображение этой "виртуальной" ячейки памяти на какую-либо физически существующую ячейку памяти. Наиболее четко необходимость в использовании виртуальной памяти проявляется в многозадачной операционной системе. Рассмотрим этот случай поподробнее:

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

Необходимо отметить, что мы не можем просто скопировать образ процесса в произвольное место памяти и запустить его. Проблема состоит во внутренних ссылках, которые присутствуют в коде (это могут быть как ссылки на данные, так и ссылки на какие-либо функции в коде и пр.). Большинство этих ссылок являются абсолютными, и пока код находится в объектном формате, каждая ссылка записывается в виде, к примеру: "адрес переменной SomeVariable: начало данных + 38 байт" или "адрес функции some_func: начало кода + 880 байт" (вообще говоря, и переменные и функции являются метками, и с точки зрения процессора разницы между ними нет).

Разумеется, процессор не может оперировать такими понятиями, как "начало секции кода" или "начало секции данных", поэтому объектный файл запустить на процессоре не получится. Задача компоновщика - разрешить все относительные ссылки (сделать относительные ссылки абсолютными). Но! Для этого он вынужден жестко определить в коде адреса начала секций (в результате этого адреса всех меток превратятся в константы, вполне воспринимаемые процессором). После этой операции код можно запускать.

Вы уже поняли суть проблемы?

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

Очевидно, что в однозадачной системе проблемы с выполнением этого требования нет - поскольку в каждый момент времени в памяти компьютера может находится только одна программа, можно выделить определенный адрес физической памяти, и компоновать все программы по этому адресу

А если система многозадачная? Одновременно в памяти находятся десятки программ, которые, заметьте, должны находится по одному и тому же адресу!

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

Изначально, виртуальная память появилась в виде сегментной организации памяти. Т.е. процесс получал в свое распоряжение сегмент памяти, а все обращения к памяти происходили внутри этого сегмента (по сути дела, сегменты представляли собой те же секции объектного файла, но уже на аппаратном уровне). К примеру, обращение к переменной, имеющей адрес 0x100 фактически осуществлялось процессором по адресу "начало сегмента данных + 0x100", а начальные адреса сегментов хранились в специальных регистрах. При переключении процессов достаточно было загрузить в эти регистры новые значения и каждый процесс оказывался в своем собственном адресном пространстве. Процессы обращались к памяти по одним и тем же адресам, но теперь эти адреса отсчитывались от базовых адресов (базовый адрес - адрес начала сегмента) сегментов, которые были разными у разных процессов. В результате, эти обращения отображались на различные части физической памяти.

Сегментация обладает рядом существенных недостатков, которые мы рассмотрим позже, и к настоящему времени уже устарела. Большинство современных процессоров не поддерживает сегментацию (одно из исключений - процессоры архитектуры IA-32, которые тянут сегментацию еще со времен 8086).

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

Суть страничной адресации в том, что все адресное пространство предоставляемое процессором (на 32-битных процессорах это, как правило, 4 гигабайта - 2**32) разбивается на отрезки равной длины (называемые страницами). И, что самое главное, программист получает возможность отобразить любую страницу виртуальной памяти на любую страницу физической памяти. Фактически, он указывает, где именно находится данная страница.

Например, программист указал, что страница памяти, находящаяся по адресу 0x80000000, отображена на следующий адрес физической памяти: 0x100000. Что же будет? Все обращения к памяти, находящейся внутри этой страницы (например к 0x80000001) будут физически осуществлены к странице по адресу 0x100000 (в нашем случае - 0x100001).

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

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

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

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

И, в завершение, рассмотрим так называемую "корову" (метод COW - copy-on-write) или механизм "копирование только при записи". Допустим, пользователь одновременно запустил два сеанса какой-либо программы. Разумеется, страницы кода будут разделятся между двумя сеансами (см. вышестоящий абзац). Но кроме кода в этих программах есть еще и данные и, более того, эти данные тоже будут разделены! Вы спросите - как?! Ведь процессы должны иметь возможность писать в область данных! Очень просто! На страницах секции данных опять же у обеих процессов ставится аттрибут "только чтение", но! При первой попытке записи (действительно, почему бы процессам не записывать что-нибудь в область данных?) в такую страницу процессор сгенерирует исключение. И уже обработчик этого исключения сделает физическую копию требуемой страницы и снимет аттрибут "только чтение" с соответствующих виртуальных страниц обеих процессов. В результате будут созданы копии только тех страниц, которые действительно в этом нуждаются. Налицо солидная экономия оперативной памяти :)

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

Outro

На сегодня все, уважаемые подписчики.
Как всегда, мой почтовый ящик открыт для вас:
lonesome@lowlevel.ru
Также вы можете задавать интересующие вас вопросы в форуме lowlevel.ru
Предыдущие выпуски рассылки вы можете найти по этому адресу:
http://subscribe.ru/archive/comp.soft.prog.osdev
А все, исходники, опубликованые в рассылке, располагаются здесь:
http://www.lowlevel.ru/osdev/sources.htm
Всего наилучшего!
Lonesome


[Главная] [Другие статьи] [Обсудить в форуме]
©2003-2004 Lowlevel.RU

Rambler's Top100