Все это совпадает с моими взглядами, и я рад, что вы думаете так же.
Некоторые люди задавали вопросы о периодичности выпусков. Могу сказать,
что делать выпуски я буду по мере возможностей, возможно чаще, чем раз в
неделю.
Начиная с этого выпуска, я начну углубляться в тонкости архитектуры и
устройства систем, если кому-то что-то становиться непонятно - пишите...
Мой адрес вы найдете в конце письма.
В этом выпуске мы поговорим об архитектуре современных процессоров и о
предоставляемых средствах защиты. Понимание этого будет необходимо нам,
когда мы перейдем непосредственно к программированию операционной системы.
Для начала небольшое предисловие.
В процессорах имеются базовые регистры, которые могут задавать смещение. На
16-битной архитектуре максимальное смещение могло быть до 64 килобайт, что,
в общем-то, не много и вызывало определенные трудности (разные модели
памяти, разные форматы файлов). Так же, в 16-битной архитектуре
присутствовали сегментные регистры, которые указывали адрес сегмента в
памяти. В процессорах, начиная с i386, базовые регистры стали 32-х битными,
что позволяет адресовать до 4 гигабайт. Сегментные регистры остались
16-битными, и в защищенном режиме они не содержат адреса! они содержат
индекс дескриптора. В реальном режиме сегментные регистры работают так же,
как и на 16-битных процессорах.
В реальном режиме сегментные регистры непосредственно указывают на адрес
начала сегмента в памяти. Это позволяет нам, без каких либо преград,
адресовать 1 мегабайт памяти. Но создает определенные трудности для защиты.
А защищать нам нужно многое. Например, мы не можем пользовательским
программам дать возможность непосредственно обращаться к коду или данным
ядра. Так же мы не можем дать возможность пользовательским программам
обращаться к коду или данным других пользовательских программ, поскольку
это может нарушить их работоспособность.
Для этого был изобретен защищенный режим работы процессора, который
появился в процессорах i286.
Защищенность этого режима заключается в следующем:
Сегментный регистр больше не указывает на адрес в памяти. В этом регистре
теперь задается индекс в таблице дескрипторов.
Таблица дескрипторов может быть глобальная или локальная (применяется в
многозадачных системах для изоляции адресного пространства задач) и
представляет собой массив записей, по 8 байт в каждой, где описываются
адреса, пределы и права доступа к сегментам.
Про адрес ничего не буду говорить, и так все ясно. Что такое предел? В этом
Поле описывается размер сегмента. При обращении за пределы сегмента
процессор генерирует исключение (специальное прерывание защищенного режима).
Так же исключение генерируется в случае нарушения прав доступа к сегменту.
Поле прав доступа описывает возможность чтения/записи сегмента, возможность
выполнения кода сегмента, уровень привилегий для доступа к сегменту.
При обращении к сегменту из дескриптора берется базовый адрес сегмента и
складывается со смещением сегмента. Так получается линейный 32-х разрядный
(в i286 - 24-х разрядный) адрес. Для i286 на этом процесс получения адреса
завершается, линейный адрес там равен физическому. Для i386 или выше это
справедливо не всегда.
В процессорах, начиная с i386, появилась, так называемая, страничная
организация памяти. Страница имеет размер 4 килобайта или 4 мегабайта.
Большие страницы могут быть только в pentium или выше. Не знаю только,
какой толк от таких страниц.
Если возможность страничной адресации не используется, то линейный адрес,
как и на i286, равен физическому. Если используется - то линейный адрес
разбивается на три части. Первая, 10-битная, часть адреса является индексом
в каталоге страниц, который адресуется системным регистром CR3. Запись в
каталоге страниц указывает адрес таблицы страниц. Вторая, 10-битная, часть
адреса является индексом в таблице страниц. Запись в таблице страниц
указывает физический адрес нахождения страницы в памяти. последние 12 бит
адреса указывают смещение в этой странице.
В страничных записях, как и в дескрипторных записях, есть служебные биты,
описывающие права доступа, и некоторые другие тонкости страниц. Одной из
важных тонкостей является бит присутствия страницы в памяти. В случае не
присутствия страницы, процессор генерирует исключение, в котором можно
считать данную страницу из файла или из swap раздела. Это сильно облегчает
реализацию виртуальной памяти. Чуть ниже мы про это поговорим.
Надеюсь, я не сильно вас утомил? более подробно про все это можно прочитать в книгах по архитектуре процессоров. А мы вернемся к операционным системам.
Многозадачные возможности в процессорах так же появились в процессорах,
начиная с i286. Для реализации этого, процессор для каждой задачи использует,
так называемый, "сегмент состояния задачи" ("Task State Segment", сокращенно
TSS). В этом сегменте, при переключении задач, сохраняются все базовые
регистры процессора, сегменты и указатели стека для трех уровней защиты
(для каждого уровня используется свой стек), сегментный адрес локальной
таблицы дескрипторов ("Local descriptor table", сокращенно LDT). В
процессорах, начиная с i386, там еще хранится адрес каталога страниц
(регистр CR3). Так же этот сегмент обеспечивает некоторые другие механизмы
защиты, но о них мы пока не будем говорить.
Операционная система может расширить TSS, и использовать его для хранения
регистров и состояния сопроцессора. Процессор при переключении задач не
сохраняет этого. Так же возможны другие применения.
В своей работе мы не будем ориентироваться на процессор i286, поскольку
16-битная архитектура и отсутствие механизма страничного преобразования
сильно усложняет программирование операционной системы. К тому же, таких
процессоров давно уже никто не использует. :)
Ориентироваться мы будем на i386 или более старшие модели процессоров,
вплоть до последних.
Ядро системы при распределении памяти оперирует 4-х килобайтными страницами.
Страницы могут использоваться самим ядром, для нужд драйверов (кэширование,
например), или для процессов.
Программа или процесс состоит из следующих частей:
Но, обычно, системы делят сегмент данных на две части: инициализированные
данные и не инициализированные данные.
Все сегменты разбиваются на страницы. Сегмент кода имеет постоянный размер.
Сегмент данных может увеличиваться в сторону больших адресов. Сегмент стека,
поскольку растет вниз, увеличивается в сторону уменьшения адресов.
Страницы памяти для дополнительных данных или стека выделяются системой по
мере необходимости.
Очень интересный момент:
При выполнении программы операционная система делает следующие действия:
Еще один интересный момент:
Когда в системе загружается две или более одинаковых программы - нет
необходимости для каждой из них выделять место для кодового сегмента, они
спокойно могут использовать один код на всех.
Ну не знаю что еще написать, жара достала, не знаю как у вас, а у нас в
Москве - за 30... :(
В следующем выпуске мы рассмотрим процессы загрузки разных операционных
систем (Windows не предлагать!). Ну, может быть еще что-то, это я узнаю из
ваших писем.
По всем вопросам вы можете обращаться ко мне по адресу: dron@infosec.ru.
При поддержке Kalashnikoff.ru
| (C)Москва, 2001. Авторское право принадлежит Валяеву А.Ю. Публичное размещение материала из рассылки, а также его использование полностью или частично в коммерческих или иных подобных целях без письменного согласия автора влечет ответственность за нарушение авторских прав. |
| http://subscribe.ru/
E-mail: ask@subscribe.ru | Отписаться | Рейтингуется SpyLog |