- Наиболее острой проблемой
многих пользователей является ненадежность
компьютеров.
- Исследователи в области компьютерной
науки привыкли к регулярным сбоям компьютеров
и к необходимости через каждые несколько
месяцев устанавливать патчи программного обеспечения. Однако подавляющее большинство пользователей считает это отсутствие надежности неприемлемым. Их внутренняя модель работы электронного устройства основывается на опыте использования телевизоров и видеомагнитофонов: вы покупаете устройство, подключаете его к сети, и оно безупречно работает в течение 10 лет.
Почему у систем случаются
отказы?
- Основная причина аварийных отказов операционных систем кроется в двух принципиальных дефектах разработки, свойственных всем этим системам: наличие слишком большого числа привилегий и отсутствие адекватной изоляции сбоев.
- Мы утверждаем, что большая часть сбоев возникает из-за ошибок программирования, вследствие чрезмерной сложности и использования чужого кода. Исследования показывают, что в программном обеспечении в среднем содержится от одной до шестнадцати ошибок на тысячу строк кода и что верхняя граница этого диапазона явно занижена, поскольку учитывались только те ошибки, которые, в конце концов, удавалось обнаружить.
- Наличие некоторых из этих ошибок
позволяет злоумышленникам применять
вирусы и черви для заражения и повреждения
системы. Так что некоторые якобы наличествующие
проблемы «безопасности» в принципе не
имеют ничего общего с нарушениями мер
безопасности (например, дефектными криптографическими
алгоритмами или неустойчивыми протоколами
авторизации), а вызываются всего лишь
ошибками в коде программ (например, переполнения
буферов позволяют выполнять внедренный
код). Когда в этой статье мы говорим о
«надежности», мы имеем в виду и то, что
часто называют «безопасностью», – неавторизованный
доступ вследствие ошибки в коде программы.
Разработка операционных систем
Этот проект посвящен построению
более надежной операционной системы.
Прежде чем подробно описывать свою разработку,
мы кратко обсудим, каким образом выбор
структуры операционной системы может
непосредственно влиять на ее надежность.
В своих целях мы будем проводить различие
между двумя структурами операционных
систем: монолитными системами
и системами с минимальным
ядром.
Проблемы
монолитных систем
Как показано на рис. 1, в стандартной
монолитной системе ядро содержит все
операционную систему, скомпонованную
в едином адресном пространстве и выполняемую
в режиме ядра. Ядро может быть структурировано
на компоненты, или модули, показанные
на рисунке в виде прямоугольников с пунктирными
сторонами, но между компонентами отсутствуют
защитные границы
Как показано на рис. 1, в стандартной
монолитной системе ядро содержит все
операционную систему, скомпонованную
в едином адресном пространстве и выполняемую
в режиме ядра. Ядро может быть структурировано
на компоненты, или модули, показанные
на рисунке в виде прямоугольников с пунктирными
сторонами, но между компонентами отсутствуют
защитные границы
Системы с минимальным
ядром
- На другом полюсе находится
минимальное ядро, содержащее только чистый
механизм и никакой политики. Поверх минимального
ядра возможны различные организации
операционной системы. Одним из вариантов
является выполнение всей операционной
системы в одном сервере в пользовательском
режиме, но в такой архитектуре существуют
те же проблемы, что и в монолитной системе,
и ошибки по-прежнему могут привести к
аварийному отказу всей операционной
системы, выполняемой в режиме пользователя.
Поверх минимального ядра возможны
различные организации операционной системы.
Одним из вариантов является выполнение
всей операционной системы в одном сервере
в пользовательском режиме, но в такой
архитектуре существуют те же проблемы,
что и в монолитной системе, и ошибки по-прежнему
могут привести к аварийному отказу всей
операционной системы, выполняемой в режиме
пользователя.
Свойства надежности
Мы считаем, что в нашей разработке
надежность системы повышается по сравнению
со всеми другими существующими операционными
системами за счет применения трех важных
подходов:
- Уменьшается число критических
сбоев.
- Сокращается объем ущерба, который
может быть причинен любой ошибкой.
- Имеется возможность восстановления
после распространенных сбоев.
Восстановление после сбоев
- Серверы и драйверы запускаются
и контролируются системным процессом,
называемым сервером реинкарнации. Если контролируемый процесс непредвиденным или аварийным образом завершается, это немедленно распознается, поскольку сервер процессов оповещает сервер реинкарнации о завершении сервера или драйвера, и процесс автоматически перезапускается.
Кроме того, сервер реинкарнации
периодически опрашивает все серверы
и драйверы на предмет их состояния. Если
какой-либо из этих процессов не отвечает
правильным образом в течение установленного
интервала времени, то сервер реинкарнации
насильственно завершает и перезапускает
плохо ведущие себя серверы и драйверы.
Поскольку очень многие ошибки ввода-вывода
бывают неустойчивыми, проявляющимися
при редко возникающих временных соотношениях,
синхронизационных тупиках и т.д., простой
перезапуск драйвера устраняет проблему.
Избегание тупиков.
- Поскольку по умолчанию для
IPC используются синхронные вызовы SEND
и RECEIVE, могут возникать тупики, когда два
или большее число процессов одновременно
пытаются обмениваться сообщениями, и
все процессы блокируются в ожидании один
другого. Поэтому мы тщательно разрабатывали
протокол избегания тупиков, предписывающий частичное, нисходящее упорядочение сообщений.
- Например, обычным пользовательским
процессам позволяется только посылать
сообщения с использованием примитива
SENDREC серверам, реализующим интерфейс
POSIX, а эти серверы могут запрашивать сервисы
от драйверов, которые, в свою очередь,
могут производить вызовы ядра. Однако
для асинхронных событий, таких как прерывания
и таймеры, требуются сообщения, посылаемые в противоположном направлении, от ядра серверу или драйверу.
Униффикация прерываний и сообщений
- Базовым механизмом IPC является
передача сообщений на основе рандеву,
но требуются и асинхронные сообщения,
например, для предоставления информации
о прерываниях, что является потенциальным
источником ошибок в операционных системах. Мы существенно уменьшили здесь
шансы на появление ошибок, унифицировав
асинхронные сигналы и сообщенияОбычно, когда некоторый процесс посылает сообщение другому процессу и получатель не является готовым, отправитель блокируется. Эта схема не работает для прерываний, поскольку обработчик прерываний не может позволить себе блокировку. Если драйвер ожидает сообщение, то оповещение доставляется напрямую. Если он его не ожидает, то оповещение сохраняется в битовом массиве до тех пор, пока впоследствии драйвер не выполнит вызов RECEIVE.
Сервер реинкарнации
- Сервер реинкарнации – это
центральный сервер, управляющий всеми
серверами и драйверами операционной
системы. Он позволяет существенно повысить
надежность, обеспечивая:
- Немедленное распознавание
фатальных сбоев.
- Периодический мониторинг состояния.
Таким образом, он помогает
отлавливать два распространенных вида
сбоев: умершие или плохо себя ведущие
системные процессы и незамедлительно
принимается за решение наиболее острой
проблемы
Надежность уровня
приложений
- Наличие сбойного драйвера
может приводить к последствиям для файловой
системы и приложений, производящих ввод-вывод.
Если у файловой системы имелся невыполненный
запрос ввода-вывода, ей будет возвращен
код ошибки, говорящий о сбое драйвера.
- На рис. 3 приводится обзор различных
сценариев восстановления на уровне приложения.
- Заключение
- Основное достижение работы,
описанной в этой статье, состоит в том,
что мы построили POSIX-совместимую операционную
систему, основанную на минимальном ядре,
исходные тексты которого составляют
менее 3800 строк. Только этот код выполняется
в режиме ядра. Насколько нам известно,
наше минимальное ядро является наименьшим
среди всех существующих ядер, которые
поддерживают полностью POSIX-совместимую мультисерверную операционную систему, функционирующую в пользовательском режиме. Уникальность нашей системы состоит также в том, что в ней каждый драйвер устройства выполняется в отдельном пользовательском процессе, и имеется возможность реинкарнации бездействующих или неверно функционирующих драйверов
на лету, без перезагрузки операционной
системы.