Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

MINIX

Введение в MINIX 3

Оригинал

www.minix3.ru

Как часто вы перезагружали ваш телевизор в прошедшем году? Вероятно, гораздо меньше, чем ваш компьютер. Конечно же, для этого есть много «резонов», но всё больше и больше пользователей, далёких от техники, не хотят и слышать о них. Они хотят только, чтобы их компьютер всё время прекрасно работал и никогда не отказывал. MINIX 3 является проектом по разработке операционной системы, надёжной, как телевизор, для встраиваемых систем и критических приложений, как, впрочем, и для будущих 50-долларовых однокристальных портативных компьютеров и настольных систем общего применения. Сегодня эта маленькая, простая и надёжная операционная система уже существует. И прошу заметить: это последняя публикация в дискуссии на тему альтернативных ОС.

Исторический экскурс

MINIX 3 имеет ясное будущее, но несколько затушёванное прошлое. Первая версия, MINIX 1, была создана в 1987 году и была первым клоном UNIX с полностью открытым исходным кодом. Она разрабатывалась быстро и скоро обрела свою собственную группу USENET (comp.os.minix) с 40'000 подписчиков в течение 3 месяцев – это большая цифра для времени, когда Интернет был доступен только исследователям из университетов и студентам. Одним из первых приверженцев MINIX был финский студент по имени Линус Торвальдс, который пошёл и купил ПК специально для того, чтобы запустить MINIX, очень тщательно изучил её и затем, вдохновлённый MINIX, решил написать свою собственную операционную систему. Хотя Линус и знал MINIX очень хорошо, он не заимствовал из неё какой-либо код, как приписывают ему некоторые. Система Линуса выросла в современную операционную систему Linux. Автор MINIX, Эндрю Таненбаум (Andrew Tanenbaum, и Торвальдс провели несколько красивых публичных дискуссий по устройству операционных систем, первую из них в 1992 году, а самую последнюю – в 2006 году (см. перевод - прим. CITKIT.ru).

Возрождение

Хотя MINIX была (и остаётся по-прежнему) широко используемым инструментом для курсов по изучению операционных систем в университетах, она получила новый импульс в 2005 году, когда Таненбаум собрал новую команду разработчиков для полной переделки её в сверхнадёжную систему. Хотя MINIX 3 и имеет общие исторические корни с MINIX 1 и MINIX 2 (реализованной в 1997 году как POSIX-совместимая ОС), но это фактически новая система (ситуация аналогична тому, как соотносятся Windows XP и Windows 3.1).

Различные исследования показывают, что программное обеспечение в общем случае содержит порядка 6÷16 ошибок на 1000 строк кода и что драйверы устройств имеют в 3÷7 раз больше ошибок, чем вся остальная операционная система. Если добавить ещё тот факт, что 70% типовой операционной системы состоит из драйверов устройств, то становится ясно, что драйверы устройств являются самым большим источником ошибок. Для Windows XP, например, 85% сбоев происходят из-за ошибок в драйверах устройств. Очевидно, для того, чтобы сделать ОС надёжной, нужно что-то сделать с этими «вредоносными» драйверами устройств. Построение системы, надёжной, несмотря на неизбежное существование ошибок в драйверах, и было главной причиной появления MINIX 3.

Конструкция

Подход, используемый в MINIX 3 для достижения высокой надёжности, основан на изоляции ошибок. В частности, в отличие от традиционных ОС, где весь код объединён в единую огромную исполняемую программу, работающую в режиме ядра, в MINIX 3 в режиме ядра работает только крошечная часть кода – всего около 4'000 строк кода. Этот код обслуживает прерывания, диспетчеризацию процессов и межпроцессное взаимодействие (interprocess communication - IPC). Оставшаяся часть операционной системы работает как набор процессов в пространстве пользователя, причём каждый из них защищён аппаратно диспетчером памяти (MMU) и ни один из них не имеет привилегий суперпользователя. Один из этих процессов, наречённый сервером реинкарнации, хранит таблицы всех остальных процессов, и когда один из этих процессов начинает работать некорректно или отказывает, сервер реинкарнации автоматически заменяет его новой копией. Поскольку многие ошибки нестабильны и возникают неожиданно, в большинстве случаев перезапуск отказавшего компонента решает проблему и позволяет системе восстановить себя без перезагрузки и без того, чтобы пользователь вообще заметил это. Это свойство называется «самовосстановление» (или «самолечение» - кому что больше нравится – прим. переводчика) и оно отсутствует в традиционных системах.

Структура MINIX 3 показана на Рис. 1. Она спроектирована как многоуровневая конструкция. Внизу находится микроядро, работающее в режиме ядра и состоящее приблизительно из 3'000 строк кода на С и 800 строк кода на ассемблере. Выше него находится уровень драйверов устройств, причём каждый драйвер является отдельным процессом в пространстве пользователя для облегчения его замены в случае, если он откажет. Затем идут серверы, которые составляют ядро операционной системы. Они включают сервер реинкарнации, упомянутый выше, файловый сервер, диспетчер процессов и др., включая Х сервер, хранилище данных (data store) и множество прочих. И, наконец, сверху расположены процессы пользователя. Хотя изнутри MINIX 3 совершенно не похожа на остальные UNIX-образные системы, она поддерживает стандартный POSIX-интерфейс приложений, так что обычное ПО для UNIX может быть довольно легко в неё портировано.


Рис. 1. Архитектура MINIX 3

Компоненты взаимодействуют между собой посылкой сообщений фиксированной длины. Например, процесс пользователя запрашивает файл, посылая сообщение файловому серверу, который в свою очередь, проверяет свой кэш и, если необходимый блок отсутствует, посылает сообщение процессу дискового драйвера начать получение блока. И хотя посылка сообщения добавляет немного дополнительного времени к длительности процесса обмена (около 500 нс на 3 ГГц Pentium 4), система остаётся вполне быстродействующей. Например, полная сборка системы, требующая более 120 компиляций, укладывается в 10 секунд.

Точка зрения пользователя

С пользовательской точки зрения MINIX 3 выглядит, как UNIX, но не такой раздутый. Она содержит X Window System и более 400 стандартных программ UNIX, включая:

  • Командные процессоры (shells): ash, bash, pdksh, rsh

  • Редакторы: emacs, nvi, vim, elvis, elle, mined, sed, ed, ex

  • Языки программирования (language tools): cc, gcc, g++, bison, flex, perl, python, yacc

  • Средства программирования (programming tools): cdiff, make, patch, tar, touch

  • Сетевые средства (networking): ssh, telnet, ftp, lynx, mail, rlogin, wget, pine

  • Файловые утилиты: cat, cp, bzip2, compress, mv, dd, uue, GNU utilities

  • Текстовые утилиты: grep, head, paste, prep, sort, spell, tail

  • Администрирование: adduser, cron, fdisk, mknod, mount, cvs, rcs

  • Игры: dungeon, nethack

В настоящее время пользовательским интерфейсом является только Х, но со временем может быть добавлен и графический пользовательский интерфейс (GUI), если подходящий лёгкий GUI найдётся. По этой ссылке можно посмотреть скриншоты.

Доступность

MINIX 3 является программным обеспечением с открытыми исходными кодами, распространяющимся под лицензией BSD. Она имеет свой собственный Интернет-сайт (http://www.minix3.org), с которого может быть скачан загружаемый образ CD-ROM, содержащий все исходники и исполняемые файлы (всё это читатели могут также найти и на сайте русскоязычной группы разработчиков ОС MINIX 3 - http://www.minix3.ru – прим. переводчика). Для её установки просто загрузите CD-ROM, войдите как root и наберите setup. Установка займёт около 10 минут. После установки системы с CD-ROM или с Интернет-сайта простым набором: packman с последующим выбором может быть загружено большое количество пакетов. В настоящее время MINIX 3 работает на платформе х86, но работа над портами на PowerPC и Xscale уже идёт. Она также прекрасно работает на виртуальных машинах, таких, как VMware и Xen.

С тех пор, как MINIX 3 была публично анонсирована в начале 2005 года, на Интернет-сайт наведалось более 300'000 различных посетителей, а образ CD-ROM был скачан 75'000 раз. В настоящее время на сайт заглядывают более 1'000 посетителей в день. Существует также активная тематическая конференция на Google USENET, comp.os.minix, где люди задают вопросы и получают ответы, сообщают о новом ПО и обсуждают MINIX 3. MINIX 3 является результатом коллективной работы и ваша помощь будет только приветствоваться. Возьмите систему, поэкспериментируйте с ней и шагните в будущее.

Дискуссия Таненбаума и Торвальдса: часть II

Оригинал (PDF)

www.minix3.ru

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

М.А. Булгаков «Собачье сердце»

Я люблю диспуты и дискуссии. Ибо, как известно, именно в спорах рождается истина. Правда, при одном условии – если стороны действительно стремятся не только довести свою точку зрения до собеседника, но и как минимум услышать друг друга. А вот с этим, как показывает жизнь, сложнее.

Видимо, именно эта причина стала поводом для появления открытого обращения Эндрю Таненбаума, которое я не преминул перевести на русский язык по причине излишней, чуть ли не болезненной (на мой личный взгляд) популярности в нашем отечестве референций к знаменитой дискуссии по поводу микро- и монолитных ядер операционных систем. Тем более, что самые ярые участники русскоязычной части «диспута», как показывает практика, даже и не пытались познакомиться с оригинальным материалом.

Попытаюсь со своей стороны этим переводом упростить задачу членам «дискуссионного клуба». И, по возможности, доставить несколько приятных минут тем, кто действительно интересуется проблемой, ибо Таненбаум как никто умеет (что большая редкость, увы, по нынешним временам) кратко и ясно излагать свои мысли. А этому у Мастера не грех и поучиться.

Оригинальный материал находится по адресу: http://www.cs.vu.nl/~ast/

Всё выглядит так, будто бы вернулись времена дебатов по поводу микроядра. Прежде, чем перейти к собственно технической аргументации, я хочу сказать пару вещей. Многие люди говорили или подразумевали, что Линус и я являемся врагами или вроде того. Это всеобщее заблуждение. Я встречал его только однажды. Он – парень «приятный во всех отношениях» и очень умный. Мы с ним можем быть несогласны в некоторых технических вопросах, но это отнюдь не делает нас врагами. Не следует путать несогласие по поводу идей и личную вражду. Я ничего не имею против Линуса и отношусь с большим уважением к тому, что он совершил.

На тот маловероятный случай, если кто-нибудь пропустил это событие, сообщаю: пару лет назад заплатила парню по имени Кен Браун () за написание книги, в которой говорилось, что Линус выкрал код Linux из моей операционной системы MINIX 1. Я очень энергично опровергал это обвинение с тем, чтобы не дать запятнать доброе имя Линуса. Я могу быть не совсем согласен с конструкцией Linux, но это его детище, а не моё, и я был очень недоволен, когда Браун сказал, будто бы он (Линус) скопировал его (Linux) с моей ОС.

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

Считается, что на здании Военно-воздушной Академии в Колорадо начертан такой девиз: «Be sure brain is in gear before engaging mouth» (что, видимо, лучше интерпретировать как аналог отечественного: «Думай, прежде чем сказать», а не переводить почти дословно: «Убедись, что врубил мозги прежде, чем разевать рот», ибо грубовато-прямолинейная форма выражения своих мыслей уместна скорее в среде доблестных американских военных, нежели в посвящённой техническим проблемам академической публикации - прим. переводчика). Я не знаю, правда это или нет, но думаю, что в любом случае идея эта хороша.

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

Простейший способ попытаться сделать это – загрузить себе MINIX 3 и поработать с ней. Она свободна и имеет открытый код (под лицензией BSD), так что, получив образ CD, вы можете записать его на CD-ROM, загрузиться прямо с него и войти в систему как Однако для того, чтобы сделать что-нибудь полезное, вам лучше выделить логический раздел на жёстком диске (1ГБ будет достаточно) и установить MINIX 3 в него. Только сначала распечатайте и прочитайте, пожалуйста, руководство по установке. Сама установка займёт около 10 минут. Затем установите с компакт-диска все пакеты, как описано в руководстве по установке. Теперь запустите X-сервер и вы сможете получить некоторый реальный опыт работы с микроядерной ОС. Попробуйте пересобрать ОС целиком, как описано в руководстве. Полная сборка - ядро плюс драйверы и все серверы в режиме пользователя (всего 125 компиляций) - займёт 5-10 секунд.

Примите, пожалуйста, к сведению, что MINIX 3 отнюдь не есть та самая ОС MINIX вашего дедушки. MINIX 1 была написана как учебное пособие; она по-прежнему широко используется в этом качестве в университетах. Эл Вудхалл (Al Woodhull) и я даже написали учебник о ней. ОС MINIX 3, естественно, основана на ней, но она (MINIX 3) изначально создавалась как высоконадёжная, самовосстанавливающаяся и не раздутая операционная система, принципиально применимая в таких проектах, как $100 ноутбук для детей из стран третьего мира и, возможно, во встраиваемых системах. MINIX 1 и MINIX 3 соотносятся так же, как 3.1 и XP: совпадает только первая часть имён. Вот почему стоит попробовать поработать с MINIX 3, даже если вы использовали MINIX 1 во время учёбы в колледже; вы будете приятно удивлены. MINIX 3 - это хоть и очень маленькая, но полнофункциональная Unix-совместимая операционная система с X, bash, pdksh, zsh, cc, gcc, perl, python, awk, emacs, vi, pine, ssh, ftp, инструментальными средствами GNU (GNU tools) и с более, чем 400 других программ. Всё это построено на крошечном микроядре и доступно прямо сейчас.

Так что, пожалуйста, не нужно больше комментариев типа «Если Таненбаум думает, что микроядра такие крутые, так что же он не сделает микроядерную ОС?» Он сделал. (На самом деле, сделали один из его студентов и двое из его программистов). Она, конечно же, пока не такая совершенная и зрелая, как Linux или BSD, но она однозначно доказывает, что создание надёжного, самовосстанавливающегося мультисерверного клона UNIX в пространстве пользователя, построенного на основе маленького и лёгкого для понимания микроядра, возможно. Только не путайте недостаточную зрелость конкретной ОС (мы работаем над ней чуть более года втроём) с различными аспектами применения микроядер в целом. Мы можем и будем со временем расширять функциональность MINIX 3, а также переносить в неё много прикладного ПО (и в этом ваша помощь очень желательна). С конца октября 2005 года, когда стартовал проект MINIX 3, уже зарегистрировано более 400,000 посещений сайта проекта. Попробуйте MINIX 3 сами и посмотрите, что получится.

Недавно мой аспирант Йоррит Хердер, мой коллега Герберт Бос и я написали статью, озаглавленную «Можем ли мы делать операционные системы надёжными и безопасными?» и послали её в IEEE Computer magazine, крупнейший журнал компьютерного сообщества IEEE. Она была принята и опубликована в майском выпуске 2006 года. В этой статье мы утверждаем, что для большинства пользователей надёжность ОС более важна, чем её производительность, и обсуждаем 4 современных исследовательских проекта, направленных на улучшение надёжности операционных систем. Три из них используют микроядра. IEEE разместил нашу публикацию на своём интернет-сайте. Затем кто-то сделал ссылку на неё на Slashdot, возобновив, таким образом, древнюю дискуссию о микроядрах и монолитных системах. И хотя я с удовольствием сознаюсь в соавторстве этой публикации, но я совсем не ожидал, что она заново перезапустит дискуссию на тему «Linux отжил своё».

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

Основная позиция Линуса заключается в том, что микроядра требуют распределённых алгоритмов и вообще очень трудносамый мягкий вариант перевода фрагмента – прим переводчика). Я согласен с тем, что распределённые алгоритмы – та ещё штуковина, хотя совместно с Маартеном ван Стином ( Maarten van Steen ) я написал книгу на эту тему. За последние десять лет я также разработал и создал две распределённые операционные системы, Amoeba (для LAN) and Globe (для WAN). Проблема с распределёнными алгоритмами заключается в отсутствии общей синхронизации процессов по времени (lack of a common time reference) вкупе с вероятностью потери сообщений и неопределённостью в том, заблокирован ли удалённый процесс или он просто проистекает слишком медленно. Однако ни одна их этих проблем не имеет никакого отношения к микроядерным ОС, работающим на одной единственной машине. Так что, хоть я и соглашаюсь с Линусом в том, что распределённые алгоритмы очень непросты, однако всё это не имеет никакого отношения к данной дискуссии.

Наоборот, хотя в нашей ОС большая часть её компонентов в пространстве пользователя и является драйверами, однако с серверами они взаимодействуют очень просто. Все драйверы символьных устройств (они читают и записывают потоки байтов) работают по практически такому же протоколу, как и все драйверы устройств с блочным доступом (которые читают и записывают блоки). Количество серверов в пространстве пользователя довольно мало: файловый сервер, сервер процессов, сетевой сервер, сервер реинкарнации, хранилище данных (data store) и ещё немного. Каждый из них имеет чётко определённую задачу и чётко определённую процедуру взаимодействия с остальными частями системы. Хранилище данных, например, отвечает за службу рассылки по списку и, соответственно, подписки не неё (publish/subscribe service), обеспечивая при необходимости слабую связь между серверами. Количество серверов, вероятно, не сильно увеличится и в будущем. Так что сложность нашей операционной системы вполне постижима и контролируема (manageable). И это отнюдь не умозрительное заключение. В конце концов, мы её уже создали. Установите MINIX 3 и потестируйте её самостоятельно.

Линус также утверждал, что разделяемые структуры данных – это хорошо. Здесь мы с ним во мнениях расходимся. Если вы когда-либо слушали курс по операционным системам, то без сомнения помните, как много времени в курсе (и места в учебнике) уделялось семафорам и синхронизации взаимодействующих процессов. Если два или более процессов могут получить доступ к одной и той же структуре данных, то вам следует быть очень-очень аккуратным, чтобы не «подвесить» себя самого. Организовать такую процедуру доступа к общему ресурсу чрезвычайно трудно даже со всеми семафорами, мониторами, мьютексами и прочими ухищрениями.

Моя точка зрения заключается в том, что следует избегать разделяемые структуры данных везде, где только можно. Системы должны строиться из наименьших модулей, полностью скрывающих свои внутренние структуры данных от кого бы то ни было. Они (модули) должны иметь чётко определённые «тонкие» интерфейсы, которыми остальные модули могут пользоваться по ходу дела. Это как раз то главное, что декларируется в объектно-ориентированном подходе к программированию: закрытие внешнего доступа к данным (hiding information), а не совместное (sharing) их использование. Я думаю, что именно закрытие внешнего доступа к данным в соответствии с подходом Дэвида Парнаса (Dave Parnas - разработчик концепции модульного проектирования, лежащей в основе современного объектно-ориентированного программирования – прим. переводчика) – вот действительно хорошая идея. Это означает, что до тех пор, пока вы сохраняете неизменным межмодульный интерфейс, вы можете свободно менять внутренние структуры данных, алгоритмы функционирования и саму конструкцию любого модуля без влияния на корректность работы системы в целом. Об этом говорится в любом курсе по проектированию программного обеспечения. Линус же фактически утверждает, что работы в области объектно-ориентированного программирования последние 20 лет шли по неверному пути. Я с этим не согласен.

И если уж однажды вы решили, что каждый модуль должен держать свои грязные лапки подальше от структур данных других модулей, то следующим логическим шагом будет помещение каждого модуля в отдельное адресное пространство и установка аппаратного диспетчера памяти (MMU) для проведения этого правила в жизнь. Применительно к операционной системе вы берёте микроядро и набор процессов из пространства пользователя, взаимодействующих с использованием механизма сообщений и чётко определённых интерфейсов и протоколов. Делается это для большей ясности и лучшей ремонтопригодности всей конструкции ОС. Естественно, Линус рассуждает на основе его опыта работы с монолитным ядром и, вероятно, на меньшей степени его знакомства с микроядрами и распределёнными системами. Мой же собственный опыт основан на конструировании, разработке и реализации мною самим множества таких операционных систем. Отсюда у нас с ним разные точки зрения на то, что является трудным, а что – нет.

Для знакомства с другой точкой зрения на проблематику надёжных операционных систем посмотрите работу Джонатана Шапиро (Jonathan Shapiro), озаглавленную Debunking Linus's Latest (что переводится примерно как «Развенчание последних утверждений Линуса» - прим. переводчика).

Годятся ли микроядра для реальной жизни?

Если кратко, то: да. На Slashdot существует бесконечное количество комментариев примерно следующего содержания: «Если микроядра такие крутые, то почему они не используются повсеместно?» На самом деле они используются. Кроме MINIX 3, существуют следующие микроядерные ОС:

  • QNX
  • Integrity
  • PikeOS
  • Symbian
  • L4Linux
  • Singularity
  • K42
  • Mac OS X
  • HURD
  • Coyotos

QNX широко используется в реальных коммерческих системах. Например, Cisco использует её в старшей модели маршрутизатора, а Cisco, смею вас заверить, ОЧЕНЬ заботится о производительности.

На военном и аэрокосмическом рынках, где надёжность является наиболее критичным параметром, одной из самых «продвинутых» операционных систем является микроядерная ОС Integrity, разработанная компанией Green Hill.

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

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

Я мог бы продолжать и продолжать, но и так уже ясно, что для приложений, где надёжность и безопасность являются критически важными, разработчики неоднократно выбирали микроядерные ОС. И хотя лично Линус может не интересоваться встраиваемыми системами реального времени (где производительность, надёжность и безопасность являются параметрами первостепенной важности), этот рынок огромен и множество действующих на нём компаний считают, что использование микроядер является способом обеспечения и производительности, и надёжности, и безопасности.

Бросив взгляд на мир персональных компьютеров, мы обнаружим там ОС L4Linux, которая была написана группой Германа Хартига (Hermann Härtig) из Технического Университета Дрездена (Technical University of Dresden - TUD). Эта ОС запускает весь Linux в пространстве пользователя поверх микроядра L4 с потерей всего лишь пары процентов производительности. Однако использование микроядра позволило людям из TUD построить на базе микроядра L4 новые системы, такие, как DROPS (система реального времени) и NIZZA (безопасность), имея при этом для обеспечения новых возможностей доступ ко всей функциональности Linux без его модификации. При таком подходе они могут экспериментировать с новой функциональностью, но при этом по-прежнему имеют возможность запускать уже существующие программы. Для исследований в области операционных систем микроядро L4 используют и другие группы, такие, как NICTA (National ICT AustraliaАвстралийский национальный центр исследований в области информационных и коммуникационных технологий – прим. переводчика) с проектом Wombat - паравиртуализованного Linux, спроектированного для поддержки работы существующих приложений на встроенных системах. Ещё одной ОС на базе L4 является TUD-OS и таких систем на самом деле много.

тоже интересуется микроядрами. Она как никто другой отчётливо понимает все проблемы сопровождения монолитных ядер. Windows NT 3.1 была нерешительной попыткой создания микроядерной системы, однако попытка эта была реализована не совсем корректно. Да и производительность ОС на оборудовании начала 90х годов также была недостаточно хороша, поэтому Microsoft на время отказалась от этой идеи. Но недавно она (Microsoft) попыталась сделать это снова, но уже на новом оборудовании, что привело к появлению ОС Singularity. Сегодня, как я вижу, многие полагают, что если Microsoft делала это, то она явно сошла с ума. Но руководившие проектом Singularity Гален Хант (Galen Hunt) и Джим Ларус (Jim Larus) – очень умные ребята и они-то как раз хорошо понимают, какую мешанину на самом деле представляет собой ОС Windows и насколько компании Microsoft необходим совершенно новый подход для её дальнейшего развития. Даже работающие над Vista люди видят, что у них имеются серьёзные проблемы. Поэтому-то они и переносят драйверы в пространство пользователя, то есть делают именно то, что я и рекомендую.

Около 10 лет назад компания IBM начала «с нуля» разрабатывать новую высокопроизводительную ОС для своих очень больших заказчиков. Объявленной целью проекта было перемещение системной функциональности из ядра в серверы и прикладные программы аналогично тому, как это делается в микроядре. Эта система, называемая К42, в настоящее время развёрнута в DoE (Department of Energy – Министерство энергетики США – прим. переводчика) и где-то ещё.

Mac OS X также является разновидностью микроядерной ОС. Изнутри она представляет собой Berkeley UNIX, функционирующий поверх модифицированной версии микроядра Mach. Однако, поскольку всё это запускается в режиме ядра (для того, чтобы выбрать всю возможную производительность), Mac OS X не является истинно микроядерной. Тем не менее, поскольку Университет Карнеги-Меллона (Carnegie Mellon University) уже много лет назад запускал Berkeley UNIX в пространстве пользователя поверх микроядра Mach, то это, вероятно, могло бы быть сделано снова, хотя и с небольшой потерей производительности, как в случае с L4Linux. В частности, существует проект Darbat по портированию кода Apple BSD (Darwin) на L4 с тем, чтобы сделать её истинно микроядерной ОС.

GNU HURD, несмотря на громкие обещания и скромные деяния, тем не менее, существует и также построена на микроядре. Даже на двух. Первая версия была построена на Mach, а вторая – на L4. Третья версия будет, вероятно, построена на ещё одном микроядре, Coyotos. HURD была разработана Ричардом Столлменом (Richard Stallman), автором emacs, gcc и множества других широко используемых программ, а также создателем лицензии GPL и лауреатом престижной награды MacArthur 'Genius' Award.

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

И это я ещё не касался гипервизоров (hypervisors), таких, как Xen и Trango, которые хотя и очень сильно отличаются от микроядер, но тоже имеют крошечный код, работающий в режиме ядра, что, по моему глубочайшему убеждению, и является ключом к построению надёжных и безопасных систем.

Несмотря на то, что MINIX 3, QNX, Integrity, PikeOS, Symbian, L4Linux, Singularity, K42, HURD, Coyotos и другие ОС представляют собой достаточно «разношёрстную компанию», достаточно очевидно, что я не одинок в попытке использовать микроядра. И если вы удивлены тем, что микроядра всё ещё не используются широко, то я отвечу, что это просто большая инерция системы. Почему Linux или Mac OS X до сих пор не заменили Windows? По той же причине: большая инерция системы. Большинство автомобилей в Бразилии могут работать на местном топливе – этаноле, поэтому Бразилия использует относительно немного нефти для автомобильного топлива. Так почему же США не делают этого и не уменьшают свою зависимость от нестабильного Ближнего Востока? По той же причине: большая инерция системы. Подвигнуть людей на изменения очень тяжело, даже в случае вполне очевидной практической выгоды.

Что я пытаюсь доказать?

На самом деле и MINIX 3, и моё исследование посвящены вовсе НЕ микроядрам, а построению высоконадёжных, самовосстанавливающихся операционных систем. Я буду считать, что эта моя работа закончена, только тогда, когда никто больше не будет производить персональные компьютеры с кнопкой RESET. У телевизоров этой кнопки нет. У музыкальных центров - тоже нет. И у автомобилей нет этой кнопки. Они битком набиты разным программным обеспечением, однако не нуждаются в таких кнопках. Компьютерам же кнопка RESET нужна только потому, что их программное обеспечение «падает» слишком часто. Я знаю, конечно, что компьютерное ПО отличается от автомобильного, но люди-то просто хотят использовать и то, и другое и совершенно не хотят выслушивать лекции о том, почему они могут рассчитывать на нормально функционирующие автомобили и не могут рассчитывать на нормально функционирующие компьютеры. Я хочу построить операционную систему, которая будет иметь характерный временной интервал между отказами, намного больший, чем время жизни компьютера, так чтобы средний пользователь никогда бы и не познакомился с отказом. У MINIX 3 есть много специфических свойств, обеспечивающих её высокую надёжность. Несмотря на то, что мы пока не реализовали все эти особенности (например, виртуальная память пока только в плане разработок на конец этого года), я думаю, что высокая надёжность – это сегодня самый большой вызов разработчикам операционных систем. Обычный пользователь не должен заботиться по поводу обновлений ПО или выжимания последних капель производительности из компьютера, однако должен беспокоиться о том, чтобы его компьютер безупречно работал все 100% времени и никогда не отказывал. Поинтересуйтесь, например, мнением вашей бабушки по этому поводу.

Чем же на самом деле микроядра в этом смысле могут быть полезны? А тем, что они делают возможным создание самовосстанавливающихся систем. Это и есть то, что меня заботит, и то, чему посвящена моя работа. Перемещение большей части ОС в группу пользовательских процессов – по одному для каждого драйвера и различных серверов – отнюдь не уменьшает количество ошибок в коде, однако существенно уменьшает возможность любой ошибки вызвать серьёзное повреждение, и к тому же сокращает размер надёжной части кода ( ). В нашей конструкции в случае отказа большинства драйверов сервер реинкарнации может перезапустить их свежую копию, а в дополнение может сохранить образ ядра «умершего» драйвера в целях отладки, зафиксировать это событие и послать e-mail администратору или разработчику и т.п. При этом система продолжает работать и только в очень крайнем случае может быть аккуратно остановлена без снижения эффективности работы или потери данных. Некоторые компоненты, такие, как собственно сервер реинкарнации, файловый сервер и сервер процессов, являются критичными и их неисправность, естественно, приведёт к отказу системы. Но нет никаких причин позволять «обрушивать» систему неисправным аудио-, принтерным или сканерным драйверам. Они просто должны быть перезапущены и работа продолжится. Это и есть наша цель: создание систем, которые могут обнаруживать свои собственные отказы и восстанавливаться после них. Вы легко можете сделать это в микроядерных системах. Сделать это в системах с монолитным ядром гораздо сложнее, хотя исследователи из Университета Вашингтона (University of Washington) выполнили неплохую работу с , да и группа из Университета Карлсруэ (University of Karlsruhe) также сделала интересную работу на основе технологии виртуальных машин.

Прежде, чем разглагольствовать о том, что микроядра могут делать, а что – не могут, лучше поработайте с MINIX 3 и станьте информированным оратором. Это повысит вашу компетентность. Для того, чтобы получше познакомиться с конструкцией MINIX 3, почитайте статью в майском номере IEEE эту статью по модульному программированию, которая только что появилась на страницах USENIX ;login, или этот технический отчёт (русский перевод всех трёх публикаций см. на сайте http://www.minix3.ru – прим. переводчика).

А если вы давно уже сделали это, то отдельное вам за это спасибо.

Эндрю Таненбаум, 12 мая 2006 г.

Модульное системное программирование в MINIX 3

Оригинал (PDF)

www.minix3.ru

Когда в начале 1960-х первые современные операционные системы только разрабатывались, разработчики были так озабочены их производительностью, что писали их на ассемблере даже несмотря на то, что такие высокоуровневые языки, как FORTRAN, MAD и Algol были уже широко признаны. Надёжность и безопасность вообще не попали в поле зрения разработчиков. Но времена изменились и сегодня нам следует пересмотреть наше отношение к надёжности операционных систем.

Если вы спросите обычных компьютерных пользователей, что они ценят менее всего в своей нынешней операционной системе, только малая их часть упомянет скорость. В остальном это будет примерно равное количество сетований на чрезмерную сложность, недостаток надёжности и безопасности в широком понимании (вирусы, черви и т.п.). Мы уверены, что большая часть этих проблем произрастает из проектных решений 40- или 50-летней давности. В частности, стремление первых поколений разработчиков поставить быстродействие превыше всего остального привела к монолитным конструкциям со всей операционной системой, работающей как единая исполняемая программа в режиме ядра. В те времена, когда максимальный объём памяти для операционной системы был только 32К слов, как было в случае с CTSS - первой ОС с разделением времени Массачусетского Технологического Института (МТИ), операционные системы со многими миллионами строк кода были просто невозможны и поэтому сложность ОС была поддающейся осмыслению и контролю.

Допустимый размер памяти рос, менялись и операционные системы, пока мы не получили нынешние операционные системы с сотнями функций, взаимодействующих таким сложным способом, что на самом деле никто не может понять вообще, как они работают. И если Windows XP с её 5 миллионами строк кода ядра является наихудшим примером с этой точки зрения, то Linux с его 3 миллионами строк кода ядра быстро продвигается по тому же пути. Мы думаем, этот путь ведёт в тупик.

Различные исследования показали, что допустимое количество ошибок в программах должно лежать в диапазоне 1÷20 на 1000 строк кода1. Более того, операционные системы обнаруживают тенденцию быть сложнее и изощрённее, чем прикладные программы, а драйверы устройств имеют на порядок большее количество ошибок на тысячу строк кода, чем вся остальная часть операционной системы2,3. Позволяя миллионам строк малопонятного кода взаимодействовать таинственным образом в пределах единого адресного пространства, не стоит удивляться, что мы имеем проблемы с надёжностью и безопасностью.

Надёжность операционной системы

С нашей точки зрения, единственным путём улучшения надёжности операционной системы является отказ от модели ОС как гигантской программы, работающей в режиме ядра, когда любая строка кода способна подвергнуть риску или вообще «уронить» систему. Почти вся функциональность ОС, и особенно все драйверы устройств, должны быть переведены в разряд процессов пользователя, оставляя только крошечное микроядро работающим в режиме ядра. Перемещение всей ОС в единый процесс пространства пользователя, как это было сделано в L4Linux4, делает перезагрузку ОС после сбоя быстрее, но не решает фундаментальную проблему потенциальной критической опасности каждой строки кода. Всё, что для этого требуется – это разделить базовую функциональность ОС, включая файловую систему, управление процессами и графику, на множество процессов, поместив каждый драйвер устройства в отдельный процесс и очень жёстко контролируя, что каждый компонент может делать. Только на основе такой архитектуры у нас на самом деле есть шанс улучшить надёжность системы.

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

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

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

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

Утверждение, что микроядра хороши с точки зрения надёжности, не ново. В 1980-х и 1990-х годах были разработаны многочисленные микроядра, включая L45, Mach6, V7, Chorus8 и Amoeba9. Никто из них не смог заменить монолитные ОС на микроядерные операционные системы, однако мы многому научились с тех пор и пришло время попытаться сделать это ещё раз. Даже Microsoft понимает это. Следующая версия Windows (Vista) будет включать множество драйверов, работающих в режиме пользователя, да и исследовательский проект Microsoft Singularity также основан на микроядре.

Архитектура MINIX 3

Для проверки наших идей мы разработали POSIX-совместимую экспериментальную систему. В качестве основы для макета мы использовали ОС MINIX по причине её чрезвычайно маленького размера и длинной истории развития. MINIX – это свободная микроядерная операционная система, которая доступна с полным исходным кодом, в большинстве своём написанном на С. Первоначальная версия была написана одним из авторов (Энди Таненбаумом) в 1987 году и была изучена многими десятками тысяч студентов в сотнях университетов за 19 лет; за последние 10 лет практически вообще не было сообщений об ошибках в ядре, по-видимому, из-за его маленького размера.

Мы начали с MINIX 2 и затем очень сильно модифицировали её, выведя драйверы из ядра и т.п., но мы решили сохранить имя и назвали новую систему MINIX 3. Она основана на микроядре, содержащем сегодня не более 4'000 строк кода, с различными серверами и драйверами в пространстве пользователя, что в совокупности образовало операционную систему, показанную на рис. 1. Несмотря на эту нетрадиционную структуру, пользователю система покажется ещё одним вариантом UNIX. Она поддерживает два компилятора С (ACK и gcc), также как и множество популярных утилит – Emacs, vi, Perl, Python, Telnet, FTP и 300 других (более 400 на сентябрь 2006 года – прим. переводчика). Ранее в неё также была портирована и система X Windows. MINIX 3 доступна на http://www.minix3.org со всеми исходными кодами и под лицензией BSD.


Рис. 1. Изображение многоуровневой архитектуры MINIX 3

Все приложения, серверы и драйверы запускаются как изолированные процессы в пространстве пользователя. Крошечное выверенное ядро является единственной частью ОС, которая запускается в режиме ядра. Расслоение является логическим, поскольку все пользовательские процессы обрабатываются ядром одинаково.

Вкратце, микроядро поддерживает аппаратные прерывания, низкоуровневое управление памятью, планирование процессов и межпроцессное взаимодействие. Последнее выполняется с помощью примитивов, позволяющих процессам посылать сообщения фиксированной длины в адрес других процессов, которым они имеют право их (эти сообщения) посылать. Большая часть взаимодействия является синхронной, при этом осуществляется блокирование отправителя или получателя сообщений в случае, если другой абонент не готов. Отправка сообщения занимает примерно 500 нс на 2,2 МГц процессоре Athlon. Хотя системный вызов обычно состоит из двух сообщений (запроса и ответа), даже 10'000 системных вызовов в секунду будут использовать только 1% CPU, так что издержки передачи сообщений практически вообще не влияют на производительность. Кроме того, существует неблокируемый механизм уведомления о событии (nonblocking event notification mechanism). Незавершённые уведомления запоминаются в компактной битовой карте, которая статически объявлена как часть таблицы процесса. Такая схема прохождения сообщений исключает все проблемы управления и переполнения буфера ядра, также, как и множество взаимоблокировок (deadlocks).

Следующий верхний уровень содержит драйверы устройств, по одному на основное устройство. Каждый драйвер является пользовательским процессом, защищённым диспетчером памяти (MMU) таким же образом, как и обычный процесс пользователя. Они (драйверы) отличаются только тем, что им позволено осуществлять небольшое число системных вызовов для получения обслуживания со стороны ядра (kernel services). Типичными вызовами ядра являются запись набора значений в аппаратный порт ввода-вывода или запрос о том, что данные будут скопированы в или из пользовательского процесса. Битовая карта в таблице процесса ядра отслеживает, какие вызовы каждый драйвер (или сервер) может делать. Ядро также знает, какие порты ввода-вывода драйверу позволено использовать; копирование оказывается возможным только с явного разрешения.

Интерфейс операционной системы формируется набором серверов. Основные из них – это файловый сервер, диспетчер процессов (process manager) и сервер реинкарнации. Пользовательские процессы осуществляют POSIX-образные системные вызовы посылкой сообщения одному из этих серверов, который затем выполняет вызов. Сервер реинкарнации представляет особый интерес, поскольку он является родительским процессом всех серверов и драйверов. Он отличается от init, от которого порождаются обычные пользовательские процессы, поскольку он управляет операционной системой и защищает её. Если сервер или драйвер отказывает или завершается иным способом, он становится «зомби» до тех пор, пока сервер реинкарнации не отловит его во время просмотра его таблиц для определения того, что следует делать. Обычной реакцией является создание нового драйвера или сервера и информирование остальных процессов о том, что было сделано.

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

Жизнь с программными ограничениями

Объяснив, почему нужны микроядра и как структурирована MINIX 3, настало самое время заняться самым главным в этой статье: моделью программирования в MINIX 3 и её применением. Ниже мы укажем некоторые отличительные свойства, сильные и слабые стороны модели программирования. Но прежде, чем мы начнём, полезно вспомнить истории о том, как ограничение программистов в том, что они могут делать, часто приводило к более надёжному коду. Рассмотрим несколько примеров.

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

Во-вторых, когда Дейкстра (E.W. Dijkstra) написал своё знаменитое письмо о вреде операторов перехода GOTO «Goto Statement Considered Harmful»10, громкие крики и стенания раздались со стороны многих программистов, которые считали, что возникла угроза их стилю написания витиеватых (spaghetti-like) программ. Несмотря на эти первоначальные возражения, идея всё же прижилась и программисты стали учиться писать хорошо структурированные программы.

В-третьих, когда было анонсировано объектно-ориентированное программирование, многие программисты игнорировали эту идею, поскольку они не могли бы больше рассчитывать на чтение или «вылизывание» структур данных внутри других объектов, что прежде являлось обычным делом во имя эффективности. Например, когда Java была представлена программистам С, многие из них усмотрели в ней аналог смирительной рубашки, поскольку они не смогли бы больше свободно манипулировать указателями. Тем не менее, объектно-ориентированное программирование сегодня повсеместно распространено и привело к созданию программного кода лучшего качества.

Ограничения MINIX 3

Аналогичным образом, модель программирования в MINIX 3 также является более ограничивающей по отношению к разработчикам операционной системы, чем было до неё, но мы считаем, что эти ограничения приведут исключительно к более надёжной системе. В настоящее время MINIX 3 написана на С, но постепенное переписывание некоторых её модулей на языке, обеспечивающем типовую безопасность (type-safe language), таком, например, как Cyclone, могло бы стать когда-нибудь возможным. Давайте начнём наш обзор модели, взглянув на некоторые из этих ограничений.

Ограниченный доступ к ядру. Ядро MINIX 3 экспортирует различные вызовы ядра для поддержки серверов и драйверов операционной системы, работающих в пространстве пользователя. Каждый драйвер и сервер имеет битовую карту в таблице процесса, ограничивающую вызовы ядра, которые он может использовать. Эта защита очень тонкая (quite fine-grained), так что, например, драйвер устройства может иметь право выполнять ввод-вывод или делать копии в и из пользовательских процессов, но не остановку системы, не создание новых процессов или установку/сброс собственно ограничений (restriction policies).

Защита памяти. В мультисерверной конструкции MINIX 3 все серверы и драйверы операционной системы запускаются как изолированные процессы пользователя. Каждый помещён в собственное адресное пространство, защищаемое аппаратным диспетчером памяти (MMU). Попытка нелегального доступа в память другого процесса приводит к нештатной ситуации MMU и вызывает немедленное уничтожение «нарушителя» диспетчером процессов. Естественно, файловой системе и драйверам устройств нужно взаимодействовать с пользовательскими процессами для выполнения ввода-вывода, но это делается через использование безопасных виртуальных копий при посредничестве ядра. Копирование другому процессу возможно только, когда есть ясное разрешение от этого процесса или от надёжного процесса (trusted process), такого, как файловая система. Эта схема снимает ответственность с драйверов и предотвращает повреждение памяти.

Ограниченный доступ к порту ввода-вывода. Каждый драйвер имеет ограниченный диапазон портов ввода-вывода, к которым он может обращаться. Так как пользовательские процессы не имеют привилегий ввода-вывода, ядро всегда посредничает в этом и может проверить, был ли разрешён запрос на ввод-вывод. Разрешённые порты ввода-вывода устанавливаются, как только драйвер стартует. Для ISA устройств это делается с помощью конфигурационных файлов, для PCI устройств набор портов ввода-вывода автоматически задаётся сервером шины PCI. Корректный набор портов для каждого драйвера сохраняется в соответствующем месте таблицы процесса драйвера (driver’s process table entry) в ядре. Такая защита гарантирует, что драйвер принтера не может случайно записать мусор на диск, потому что любая попытка записи в порт ввода-вывода диска будет приводить к неудачному вызову ядра. Серверы и обычные пользовательские процессы вообще не имеют доступа к какому бы то ни было порту ввода-вывода.

Ограниченное межпроцессное взаимодействие. Процессы не могут посылать сообщения к случайным процессам. Кроме того, ядро отслеживает, кто с кем может общаться, и предотвращает нарушения. Разрешённые функции и адресаты IPC устанавливаются сервером реинкарнации при запуске нового системного процесса. Например, драйверу может быть разрешено взаимодействовать только с файловым сервером и ни с каким другим процессом. Эта возможность устраняет некоторые ошибки, когда процесс пытается послать сообщение другому процессу, который его (сообщение) не ожидает.

Разработка операционной системы в пространстве пользователя

А сейчас давайте посмотрим на остальные аспекты модели программирования в MINIX 3. Несмотря на существование вышеупомянутых ограничений, мы полагаем, что программирование в среде мультисерверной операционной системы имеет множество преимуществ и может привести к более высокой производительности и лучшему качеству кода.

Короткий цикл разработки. Огромная разница между монолитной и мультисерверной ОС сразу же становится ясной, как только вы обратите внимание на цикл разработки компонентов операционной системы. Системное программирование в монолитной ОС обычно включает редактирование, компиляцию, пересборку ядра и перезагрузку для проверки нового компонента. последующий сбой может потребовать ещё одной перезагрузки с последующей утомительной низкоуровневой отладкой, зачастую даже без дампа ядра. В противоположность этому, цикл разработки на мультисерверной ОС, такой, как MINIX 3, существенно короче. Обычно шаги ограничиваются редактированием, компиляцией, тестированием и отладкой. Далее мы детально рассмотрим эти шаги.

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

Никакого вынужденного простоя системы. Неизбежные перезагрузки монолитных ОС практически добивают всех пользователей, вынуждая их предпочесть определённые инструментальные средства разработки. В MINIX 3 для тестирования новых компонентов никаких перезагрузок не требуется, так что остальных пользователей это никак не задевает. Более того, ошибки или другие проблемы изолированы в новом компоненте и не касаются системы в целом, поскольку новый компонент запускается как независимый процесс в ограниченной среде исполнения. Проблемы, таким образом, не могут распространяться, как в монолитном ядре.

Лёгкая отладка. Отладка драйвера устройства в монолитном ядре – это реальная проблема. Зачастую система сразу же останавливается и программист не получает ответа на вопрос о том, что пошло не так. Использование симулятора или эмулятора обычно бесполезно, поскольку, как правило, устройство, для которого пишется драйвер, очень новое и не поддерживается симулятором или эмулятором. В противоположность этому, в модели MINIX 3 драйвер устройства – это просто пользовательский процесс, так что, если он «рухнет», это произойдёт вне дампа ядра, который может быть проанализирован любым нормальным средством отладки. В дополнение, выход всех операторов printf() в драйверах и серверах автоматически направляется в лог-сервер, который пишет всё это в файл. После неудачного запуска нового драйвера программист может просмотреть лог с тем, чтобы увидеть, что драйвер сделал перед тем, как «умереть».

Низкий барьер для доступа. Так как написание драйверов и серверов в MINIX 3 гораздо легче, чем в обычных ОС, то исследователи и другие не профессиональные программисты легко могут попытаться написать новые. Лёгкость экспериментирования может существенно развить систему, позволяя людям с хорошими идеями, но малым опытом системного программирования попытаться реализовать их идеи и строить макеты, которые они никогда бы не создали в монолитных ядрах. Хотя наитруднейшая часть написания нового драйвера устройства требует понимания реальной аппаратной части, остальные компоненты ОС могут быть реализованы совсем легко. Например, демонстрационный пример в конце этой статьи иллюстрирует, как в MINIX 3 могут быть добавлены семафоры.

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

Хорошая отслеживаемость. Когда драйвер или сервер «падает», то совершенно очевидно, что именно «упало» (так как его «родитель», сервер реинкарнации, знает, какой процесс завершил работу). Как следствие, гораздо легче, нежели в монолитных системах, отловить, чьей ошибкой был вызван сбой и, возможно, кто конкретно должен ответить за произошедшее. Так что, делая изготовителей коммерческого программного обеспечения ответственными за их ошибки абсолютно таким же способом, как и изготовителей шин, лекарств и другой контролируемой продукции, можно улучшить качество программного обеспечения.

Большая гибкость. Наша модульная модель предлагает большую гибкость и делает системное администрирование гораздо легче. Поскольку модули ОС – это всего лишь процессы, то их относительно просто заменять. Становится легче конфигурировать ОС, добавляя и настраивая отдельные модули. Более того, если необходимо исправить драйвер устройства, то обычно это можно сделать «на лету», без прекращения обслуживания или остановки системы. Замена модуля в монолитных ядрах гораздо труднее и часто требует перезагрузки. И, наконец, поддержка также становится легче, поскольку все модули малы, независимы и совершенно понятны.

Пример: управляемое сообщениями программирование в MINIX 3

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

Семафоры являются положительными целыми, равными или большими нуля, и поддерживают две операции – UP и DOWN, для синхронизации нескольких процессов, пытающихся получить доступ к разделяемому ресурсу. Операция DOWN на семафоре S уменьшает S до тех пор, пока S не станет равно нулю, и в этом случае он блокирует вызывающий процесс до тех пор, пока какой-нибудь не увеличит S с помощью операции UP. Такая функциональность в монолитной системе является типичной частью ядра, но в MINIX 3 может быть реализована как отдельный сервер из пространства пользователя.

Структура семафорного сервера в MINIX 3 показана на рис. 2. После инициализации сервер входит в основной цикл, который продолжается бесконечно. В каждой итерации сервер блокирует и ожидает поступления сообщения-запроса (request message). Как только сообщение получено, сервер проверяет запрос. Если тип запроса известен (допустим), то для обработки запроса вызывается связанная с ним функция обработки и результат возвращается для того, чтобы отправитель не был заблокирован. Неверные типы запросов немедленно приводят к неверному ответу.

Как говорилось выше, обычные пользовательские процессы в MINIX 3 ограничены в части синхронной посылки сообщений. Запрос заблокирует отправителя до тех пор, пока не придёт ответ. Мы воспользуемся этим при построении семафорного сервера. Для операций UP сервер просто увеличивает значение семафора и немедленно посылает ответ для того, чтобы отправитель мог продолжить работу. Для операций DOWN наоборот, ответ будет задержан до тех пор, пока значение семафора будет уменьшаться, таким образом эффективно блокируя отправителя до тех пор, пока он не будет должным образом синхронизирован. Семафор имеет связанную с ним очередь процессов (FIFO), для отслеживания блокированных процессов-отправителей. После операции UP очередь проверяется для того, чтобы посмотреть, разблокирован ли ожидающий процесс.

void semaphore_server( ) {
message m;
int result;
/* Initialize the semaphore server. */
initialize( );
/* Main loop of server. Get work and process it. */
while(TRUE) {
/* Block and wait until a request message arrives. */
ipc_receive(&m);
/* Caller is now blocked. Dispatch based on message type. */
switch(m.m_type) {
case UP: result = do_up(&m); break;
case DOWN: result = do_down(&m); break;
default: result = EINVAL;
}
/* Send the reply, unless the caller must be blocked. */
if (result != EDONTREPLY) {
m.m_type = result;
ipc_reply(m.m_source, &m);
}
}
}

Рис. 2. Основной цикл сервера, использующий один семафор S

Все серверы и драйверы имеют аналогичный основной цикл. Функция initialize() вызывается один раз перед входом в основной цикл, но она здесь не показана. Функции обработки do_up() и do_down() приведены на Рис. 3.

Используя структуру семафорного сервера, мы должны организовать и взаимодействие с ним пользовательских процессов. Как только сервер запустится, он будет готов обслуживать запросы. В принципе, программист может сконструировать сообщения-запросы и послать их новому серверу, используя ipc_request(), но такие мелочи обычно скрыты в системных библиотеках наряду с остальными POISIX-образными функциями. Как это обычно принято, новые библиотечные вызовы sem_up() и sem_down() следовало бы добавить в libc для обработки этих вызовов. И хотя наш демонстрационный пример описывает очень упрощённый семафорный сервер, он легко может быть расширен и для обеспечения соответствия семафорным спецификациям POSIX, и для обработки многих семафоров и т.п.

Модульная структура MINIX 3 помогает ускорить разработку семафорного сервера несколькими способами. Во-первых, он может использоваться независимо от остальной части ОС, просто как обычное пользовательское приложение. Когда же он будет закончен, он может быть скомпилирован как автономное приложение и динамически запускаться, чтобы стать частью операционной системы. Нет необходимости строить новое ядро или перезагружать систему, что предотвращает простои системы и защищает других пользователей от неожиданных сбросов системы, отключения от Интернета, почтовых и FTP серверов и т.п. Когда сервер запустится, его привилегии ограничиваются в соответствии с принципом минимальных полномочий, так что тестирование и отладка нового семафорного сервера могут быть выполнены без какого бы то ни было влияния на остальную часть системы. Как только он готов, сценарий запуска может быть сконфигурирован для автоматической загрузки семафорного сервера во время инициализации операционной системы.

          int do_down(message *m_ptr) {

/* Resource available. Decrement semaphore and reply. */
if (s > 0) {
s = s – 1; /* take a resource */
return(OK); /* let the caller continue */
}
/* Resource taken. Enqueue and block the caller. */
enqueue(m_ptr->m_source); /* add process to queue */
return(EDONTREPLY); /* do not reply in order to block the caller */
}
int do_up(message *m_ptr) {
message m; /* place to construct reply message */
/* Add resource, and return OK to let caller continue. */
s = s + 1; /* add a resource */
/* Check if there are processes blocked on the semaphore. */
if (queue_size() > 0) { /* are any processes blocked? */
m.m_type = OK;
m.m_source = dequeue(); /* remove process from queue */
s = s – 1; /* process takes a resource */
ipc_reply(m.m_source, m); /* reply to unblock the process */
}
return(OK); /* let the caller continue */
}

Рис. 3. Операторы up и down семафорного сервера

Функции enqueue(), dequeue() и queue_size() выполняют управление очередью (list management) и не показаны.

Заключение

MINIX 3 является новой, полностью модульной операционной системой, сконструированной для того, чтобы быть сверхнадёжной. Как и в случае других новшеств, наше стремление к надёжности налагает некоторые дополнительные ограничения на условия выполнения программ, но мультисерверная среда MINIX 3 делает жизнь системного программиста гораздо легче. Цикл разработки оказывается короче, вынужденный простой системы более не является неизбежным, программный интерфейс оказывается более POSIX-образным, а тестирование и отладка становятся легче. Производительность труда программиста, скорее всего, увеличивается, а качество кода может быть улучшено за счёт лучшей отслеживаемости. Системный администратор также вознаграждается, поскольку MINIX 3 улучшает конфигурируемость и удобство обслуживания операционной системы. И, наконец, мы проиллюстрировали управляемую сообщениями модель программирования в MINIX 3 на примере создания простого семафорного сервера и обсудили вопрос о том, в чём и как его разработка выигрывает от модульности MINIX 3. Интересующиеся читатели могут загрузить MINIX 3 (включая все исходные тексты) с http://www.minix3.org. Более 50'000 человек уже скачали её; попробуйте и вы.

Ссылки

[1] T.J. Ostrand and E.J. Weyuker, “The Distribution of Faults in a Large Industrial Software System,” Proceedings of the SIGSOFT International Symposium on Software Testing and Analysis, ACM, 2002, pp. 55–64.

[2] A. Chou, J. Yang, B. Chelf, S. Hallem, and D. Engler, “An Empirical Study of Operating System Errors,” Proceedings of the 18th ACM Symposium on Operating System Principles, 2001, pp. 73–88.

[3] M.M. Swift, M. Annamalai, B.N. Bershad, and H.M. Levy, “Recovering Device Drivers,” Proceedings of the 6th Symposium on Operating System Design and Implementation, 2004, pp. 1–15.

[4] H. Härtig, M. Hohmuth, J. Liedtke, S. Schönberg, and J. Wolter, “The Performance of μ-Kernel–Based Systems,” Proceedings of the 16th Symposium on Operating System Principles, 1997, pp. 66–77.

[5] J. Liedtke, “On μ-Kernel Construction,” Proceedings of the 15th ACM Symposium on Operating System Principles, 1995, pp. 237–250.

[6] M. Accetta, R. Baron, D. Golub, R. Rashid, A. Tevanian, and M. Young, “Mach: A New Kernel Foundation for UNIX Development,” Proceedings of the USENIX 1986 Summer Conference, 1986, pp. 93–112.

[7] D.R. Cheriton, “The V Kernel: A Software Base for Distributed Systems,” IEEE Software, vol. 1, no. 2, 1984, pp. 19–42.

[8] A. Bricker, M. Gien, M. Guillemont, J. Lipkis, D. Orr, and M. Rozier, “A New Look at Microkernel–Based UNIX Operating Systems: Lessons in Performance and Compatibility,” Proceedings of the EurOpen Spring 1991 Conference, 1991, pp. 13–32.

[9] S. Mullender, G. Van Rossum, A.S. Tanenbaum, R. Van Renesse, and H. Van Staveren, “Amoeba: A Distributed Operating System for the 1990s,” IEEE Computer Magazine, vol. 23, no. 5, 1990, pp. 44–54. [10] E.W. Dijkstra, “Goto Statement Considered Harmful,” Communications of the ACM, vol. 11, no. 3, 1968, pp. 147–148.

апрель 2006


Йоррит Н. Эрдер (Jorrit N. Herder) в настоящее время получает степень доктора философии на отделении компьютерных систем Департамента компьютерных наук университета Врийе, Амстердам. Его научные интересы связаны с разработкой и применением безопасных и надёжных операционных систем. Эрдер получил степень магистра естественных наук в университета Врийе. Связаться с ним можно по адресу jnherder@cs.vu.nl.

Герберт Бос (Herbert Bos) является доцентом отделения компьютерных систем Департамента компьютерных наук университета Врийе, Амстердам. Его научные интересы включают современные средства организации сетей (advanced networking technology), операционные системы и компьютерная безопасность. Бос получил степень доктора философии в Кембриджском университете. Связаться с ним можно по адресу bos@cs.vu.nl.

Бен Грас (Ben Gras) имеет степень магистра в области компьютерных наук университета Врийе, Амстердам, а до этого работал системным администратором и программистом. В настоящее время он приглашён университетом Врийе в группу компьютерных систем в качестве программиста для работы над проектом MINIX 3. Связаться с ним можно по адресу bjgras@cs.vu.nl.

Филип Хомбург (Philip Homburg) получил степень доктора философии университета Врийе в области глобальных распределённых систем (wide-area distributed systems). До присоединения к этому проекту он занимался вопросами виртуальной памяти, построения сетей и X Windows в проекте Minix-vmd и работал над усовершенствованными файловыми системами (advanced file systems) в проекте Logical Disk. Связаться с ним можно по адресу philip@cs.vu.nl.

Эндрю С. Таненбаум (Andrew S. Tanenbaum) является профессором в области компьютерных наук (computer science) университета Врийе, Амстердам. Его научные интересы связаны с операционными системами и компьютерной безопасностью. Таненбаум получил степень бакалавра в Массачусетском Технологическом Институте и степень доктора философии в Калифорнийском Университете в Беркли. Он является членом Института инженеров по электротехнике и электронике (IEEE) и членом Ассоциации по вычислительной технике (ACM). Связаться с ним можно по адресу ast@cs.vu.nl.

Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье