"Зачем?", "Почему?", и "Куда?" или Всякое разное про операционные системы. Часть 1
АрхивТехнологизмы (архив)О причинах возникновения и смысле существования такого распостраненного класса программ, как Операционные Системы.
Этот текст был написан автором после того, как в одном из наших форумов я увидел постинг с призывом принять участие в разработке новой ОС и предложил автору выразить свои мысли в форме статьи. Поэтому, если Вы разделяете взгляд автора, то свяжитесь с ним — возможно это приведет к новым интересным разработкам.
wsDmitry
Сначала я постараюсь доказать Вам, уважаемый читатель, что операционная система иногда оказывается полезной.
На самом деле, ОС не нужна в большинстве случаев. Например, в каком-нибудь телевизоре или видеомагнитофоне или стиральной машине прекрасно работают программы, которые могут выполнять Ваши команды и которые могут управлять этой бытовой техникой согласно заданному расписанию. Или взять процессоры Intel: там тоже есть программы, их даже обновлять можно (секция 8.11, IA-32 Intel Architecture Software Developer's Manual, volume 3, System Programming Guide), и они довольно хорошо обходятся без операционной системы. А говорить о всяких пейджерах и не приходится. Думаю, даже на основе этих примеров можно понять, что в большинстве случаев ОС программам не нужна. Но если всё так, то откуда у Microsoft столько денег?
Ответ довольно прост. И, как обычно, заключается он в вопросах «зачем?» и «что делать?».
Зачем нужна программа? Чтобы автоматизировать некоторые действия, чтобы, грубо говоря, Вам не приходилось лезть в память пейджера с вольтметром и на основе показаний, снятых с триггеров его памяти, восстанавливать сообщение. Вам не приходится это делать благодаря алгоритмам, реализованным в нём аппаратно, с помощью логических элементов и связей между ними, а также программно в виде программ (простите за тавтологию). В результате «чудо-дивайс» может всё это проделать гораздо быстрее и надёжнее Вас.
Ну а что делать, если «программных» программ много? Если нет ничего внешнего по отношению к этому набору программ, то сделать ничего не получиться. Это нужно даже в случае одной программы, и если о функционировании процессора и памяти позаботилась матушка природа (да и то, вначале было слово), то об остальном должны договориться мы. Так, когда процессор стиральной машины готов выполнять инструкции, он выбирает первую из ячейки памяти, адрес которой задаётся физической организацией системы. В принципе, законы природы не запрещают ему начать выборку инструкций с произвольного адреса, но программисты должны знать, где располагать первую инструкцию своей программы. Появилось правило — соглашение между программистами и разработчиками аппаратной платформы. И это нечто внешнее по отношению к самой программе, в принципе, не нужное, но без этого ничто не заработает.
Но, всё-таки, что делать, когда программ много? Можно ничего не делать. Просто, когда выполнилась одна программа, помещать на её место другую или замещать инструкцию, с которой процессор начинает выполнение, инструкцией передачи управления на новую программу. Но делать это вручную, внешними к системе способами. Но не дешевле ли этот процесс автоматизировать? Вместо кучи людей, которые переписывают программы из одного места в другое или программаторами меняют Первую Инструкцию, и которым (и это самое главное) надо платить кучу денег, написать программу, которая будет уметь запускать другие программы и ввести соглашение о том, что любая другая программа должна будет после завершения своей работы некоторым образом передавать Первой Программе управление. При этом всём не нужно придумывать новые процессоры, потому что операторы безусловного перехода давно есть. Оказалось, что это дешевле. Примерно так появилась первая ОС.
Ну а потом пошло-поехало. Если у нас несколько программ, то отчего бы не убрать того человека, который запускает эти программы одну за другой? Это вполне можно автоматизировать. А если у нас куча процессоров, и программа не использует все из них, то почему бы другие не заставить выполнять другую программу? Это сложнее (кажется, эффективное распределение ресурсов — NP полная задача), но тоже выполнимо. А потом появились внешние устройства и прерывания. Так почему бы, когда одна программа ждёт нажатия клавиши, не остановить её, и, пока не возникло нужное прерывание, выполнять другую программу? А почему так поступать только при ожидании клавиатуры, отчего не работать в подобном режиме с дисками, ведь они обзавелись своими процессорами (хорошо известными, как контроллеры или каналы)? Время, как говориться, деньги, особенно процессорное время. Вот. Так и дожили мы до того, что называется Windows XP ( хотя, не следует думать, что она занимается только этим ). Конечно, увидев слово «потом», как и в любой другой истории, следует ухмыльнуться и простить автору столь неадекватный взгляд на ход событий.
Итак, теперь ясно, чему посвящена часть кода ОС. Автоматизированию управления выполнением приложений. Другая же часть повешена абстракционизму. То есть обеспечению некоторых договорённостей о программно-аппаратном интерфейсе. Например, поддержка таких абстракций, как файл, сокет или терминал. Зачем их поддерживать? Ответ очевиден: деньги, деньги и ещё раз деньги! Чтобы не нужно было переписывать программу при переоборудовании вычислительного центра. А Вы что думали? Драйвера только в windows появились? Чтобы Вам в игрушки играть легче было? Ан нет! Если программа напрямую будет работать с аппаратурой, то что делать если поменялся компьютер, на которой её запускали? Делать нечего надо переписывать весь код, который работал с дисками, например. А если эти диски, ко всем прочим достоинствам, имеют непонятный для обывателя интерфейс? Нет, не зря раньше программистам деньги платили! Впрочем, одна программа — это не беда. Под DOS с проблемой успешно справлялись. А если у нас Вычислительный центр, если у нас куча пользователей, которых надо заставить переписать программы?
А вот если у нас поддерживаются некоторые абстракции, то можно не переписывать каждую программу, а переписать только библиотеки, которые поддерживают нужные абстракции, а дальше дело за компиляторами, теорией синтаксического анализа, математикой, законами логики и философскими размышлениями о природе вещей.
Впрочем, переписывание библиотек для каждого нового устройства — весёлое по своей сути занятие — превратилось в головную боль для создателей ОС, когда устройств стало много, а стандартов на их интерфейсы — мало. В этот момент кто-то придумал переложить написание специфичного для данного устройства кода на плечи разработчиков этих устройств. А чтобы это всё работало, договориться о правилах, согласно которым этот код должен быть организован. Воистину: хаос (разнообразие интерфейсов устройств) порождает порядок (правила функционирования драйверов)!
Итак. Теперь ОС — это то, что управляет программами, поддерживает некоторый механизм (механизм управления ресурсами) для общения приложений с драйверами и ограничивает полёт фантазии разработчиков последних некоторыми правилами, которые связаны, в основном, с тем, что работать драйверу предстоит там, где доступ к аппаратному ресурсу хотят получить многие приложения.
И ещё одно. ОС должна обеспечить взаимодействие приложений. Если речь идёт о Вашем PC, то есть горячее желание быстро и удобно передавать данные из одной программы в другую. Если речь идёт о ВЦ (вычислительном центре), то есть ещё более горячее желание, потому что вычисления, в основном, параллельные, а во время параллельных вычислений часто нужно обеспечивать хотя бы синхронизацию. Сложность системы, по сравнению с тем же пейджером, возрастает на порядки! Остальное, на мой взгляд, частности, и мы будем считать, что картина ОС сформирована.
Конец введения. Теперь по сути.
Теперь обратим свои взоры на войну. Войну, которую отчаянно ведут в форумах по всему миру «юниксоиды» и «виндусоиды». Уже несколько лет они портят свои клавиатуры и тратят время на восхваление своей ОС. Эх, если бы их энергию, да в созидательных целях. Очень даже интересно узнать, сколько в этом споре создано мегабайтов текста.
На мой взгляд, эти споры бессмысленны. Ибо они подобны спору о том, какой холодильник морозит сильнее: белый или бежевый. Нет, конечно, есть разница — бежевый на солнце греется сильнее. Но существенен ли этот нагрев? При чём здесь это? Просто изнутри что юникс (линукс), что виндоус — одно и то же, не в смысле реализации, а идейно.
Прочитайте следующее, помня, что я говорю о одиночной машине, не о кластере. У нас есть процессы, изначально абсолютно изолированные друг от друга, каждый из которых представлен одним или несколькими нитями, каждый «думает», что только он работает на компьютере. У нас есть библиотеки, динамически или статически связываемые с программами, доступ к аппаратным ресурсам осуществляется с помощью драйверов (модулей ядра), выполняемых на уровне ядра ОС (то есть эти драйвера имеют доступ ко всей памяти приложений). Запрос операционной системы происходит через прерывание, синхронизация осуществляется с помощью семафоров, со счётчиками или без них, процессы взаимодействуют через передачу сообщений (сигналов, информации через pipe — это всё из одной оперы. Ядро копирует информацию из памяти одного процесса в память другого), общую память (когда приложения могут обращаться к одному, логическому или физическому, куску памяти. Это самый быстрый способ взаимодействия приложений в традиционных ОС, самый опасный, и требующий постоянно анализировать адресные пространства взаимодействующих таким образом приложений), которая появилась не сразу, и её введение в архитектуру существенно осложняет жизнь тем, кто пишет ядро, особенно механизм подкачки, или через механизм вызова удалённых процедур, который требует использования нетривиальных протоколов обмена информацией, создания заглушек и скелетов, да ещё кучи всякой радости, при этом вся эта радость суть раскачанные протоколы передачи сообщений.
Прочитали? А теперь, укажите мне на то, про что Вы можете сказать: «Это есть в моей любимой ОС, а в нелюбимой нет» (впрочем, слова «любимой» и «нелюбимой» можно переставить ).
А теперь, я попробую убедить Вас, что всё можно сделать гораздо лучше. Впрочем, лучше — растяжимое понятие. И, справедливости ради, замечу, что разработчики не спят и многое делают. При этом «ненавистный» Билл даже опережает «не менее ненавистного» (для другой части компьютерного общества) Линуса.
Первое. Зачем и как расщеплять ядро. Но начну я немного слева. С идеи микроядра. Я не знаю откуда она появилась, но подозреваю, что из-за лени, ибо весь прогресс из-за неё родимой и происходит. Идея такая: «Не нужно писать ядро так, чтобы оно могло удовлетворить все запросы приложения. Не нужна нам куча всего для поддержки разных устройств, тем более, что мы не знаем о тех устройствах, которые захотят использовать пользователи. Вместо этого мы создадим такое ядро, которое обеспечит минимальный набор необходимых для функционирования и взаимодействия приложений и драйверов абстракций, при этом неплохо, чтобы драйверы не отличались от обычных приложений». Вот. К абстракциям отнесли такие понятие, как виртуальная память, сообщения, порты ввода-вывода, задачи, нити. И ещё много чего, в том числе и лишнего. Первым целенаправленно разработанным микроядром было ядро Mach (между прочим, читается «мак»), сделали его в университете Юты. Но, как оказалось, это микроядро было довольно громоздким и медленным. Впрочем, свою основную роль сыграло — микроядер после него появилось много. Но ведь оно было громоздким и медленным, скажите Вы, почему же идея стала популярной? По моему, причина в следующем: для того, чтобы написать что-нибудь новенькое и системное (драйвер новой сетевой карты, который должен иметь Ваш супер-пупер гибкий и универсальный механизм взаимодействия с пользователем) для обычной операционной системы, вы должны переписать ядро, затем перекомпилировать его, перезагрузиться, посмотреть, как оно работает, если что-то не так, то исправить ошибки и всё снова. А в случае микроядерной ОС, если у Вас уже есть отлаженные текстовый редактор, компилятор и, гм, отладчик, Вы можете написать свой драйвер, скомпилировать его и отладить «на ходу». На лицо ускорение процесса разработки, потому что, как минимум, вы не тратитесь на перезагрузку. А когда вы его запустите, можно быть уверенным, что любимый драйвер не повесит систему намертво, ибо микроядро обеспечивает некоторую изоляцию от него других приложений, например, выделяет ему его собственное адресное пространство, разрешая взаимодействовать с другими приложениями только через передачу сообщений. И помимо этого, микроядро позволяет системе быть невообразимо (по меркам стандартной ОС) гибкой. Имея микроядерную архитектуру очень просто проделывать такие вещи, как размещать ОС на любой файловой системе (если драйвер файловой системы реализует заранее оговоренный интерфейс, то какая кому разница, как он это делает?), с лёгкостью выгружать любые ненужные драйверы, например, драйверы консоли (в самом деле, зачем ftp серверу иметь клавиатуру и монитор? Отключить-то их физически можно, но вот программный кусок в памяти останется, неэкономно), с лёгкостью можно создавать распределённые системы, потому что все программы взаимодействуют с помощью обмена информацией через обмен сообщениями или общую память. Первое можно напрямую пустить через сеть, а для второго есть алгоритмы, которые позволяют эффективно поддерживать её консистентность, т.е., условно говоря, одинаковость на всех узлах системы (проект munin, кроме того, могу посоветовать заглянуть сюда). И еще одно немаловажное свойство — переносимость. Микроядро позволяет довольно хорошо абстрагировать такие вещи, как процессор и память. Пример тому L4: чтобы перенести DROPS (одна из операционных систем, построенных на базе L4) с платформы x86 на Alpha, необходимо всего лишь ее перекомпилировать!
Впрочем, mach был медленным, точнее — неприемлемо медленным. Когда Вы отделяете драйвер устройства от ядра, делая его обычным приложением, Вы должны придумать механизм, который позволит быстро передавать информацию между приложениями. Передача сообщений, которая использовалась в первых mach'ах тут мало помогает, потому что приходится копировать большие объёмы информации. На это и упирали разработчики обычных операционных систем. Ведь у них драйверы видеокарт имели доступ ко всей памяти приложений. Упирали они долго, пока не появились микроядра семейства L4 (читается «элфир». В отличии от «мак» не несет никакой смысловой нагрузки, но звучит), в которых была решена эта проблема. При этом решена хорошо и с экономией памяти: реализация L4 для x86 занимает 12Kb! Чтобы вы не подумали, что я "K" спутал c "M", повторю: 12Kb. Ну что, господа — любители Linux? Вы скажите, что драйверов в нём нет? Да, нет, но довольно накачанный DROPS занимает всего одну дискету, при этом можно повыгружать половину этой ОС, например, шелл, терминал, драйверы дисководов, сидиромов, последовательных портов…, затем переконфигурировать адресные пространства так, чтобы все память видеокарты использовалась как обычная… Зачем Вам такая радость нужна? Например, чтобы запустить ftp сервер, а за счёт сэкономленной памяти увеличить количество возможных подключений. Но вернёмся к быстродействию. L4Linux (с микроядром L4-fiasco), почти не отстаёт, а иногда даже и «делает» Linux. А всё благодаря тому, что Йохен Ляйдтке (Jochen Leidtke, к сожалению, покойный), создатель L4, предложил нехитрый механизм конструирования виртуальных пространств. Всё гениальное — просто. Он предложил организовывать адресные пространства иерархически, что помогло создавать общую память для задач и обслуживать её довольно эффективно, без потери стабильности и безопасности, что позволило программам обмениваться с драйверами информацией достаточно быстро. Ляйдтке предложил ещё много интересных идей в L4, так много, что ему отдали целую лабораторию в IBM, а L4 породило столько вариаций, что и в сказке сказать и пером описать, только долго (на самом деле это просто интерфейс, его реализаций много. Это ещё показывает, что на микроядрах очень легко обкатывать новые технологии в области управления выполнением. Не нужно переписывать всю ОС для этого надо лишь переписать микроядро. Адепты L4 за последние несколько лет много всего усовершенствовали, благодаря желанию запустить на своей реализации микроядра L4Linux как можно быстрее).
Вы можете сказать, что это от Вас далеко и никому не нужно. L4 никогда Вы не видели, а о Mach слышали только от Линуса, когда он наводил критику. Я скажу, что Microsoft Windows NT/2000/XP — системы, построенные на базе микроядра (со странностями, но микроядра: чтобы понять это, прочитайте помощь в каком-нибудь Driver Development Kit ). 4.4BSD Lite — это система, построенная на базе mach 4.0, Mac OS X — тоже. Доходит даже до экстремизма: например, IBM будущее ОС для ПК и КПК видит только в связке L4Ka (вариация на тему L4 из университета города Карлсруэ) и SawMill (нечто подобное L4Linux, разрабатываемое под патронажем IBM). Вспомним и милый сердцу plan 9, от которого современные системы так много набрали, который тоже был микроядерным.