Современные операционные системы на деле вовсе не так современны — практически все их многообразие реализует единственную концептуальную модель, сформулированную еще в середине XX века при создании ОС Unix, на которой базируются и популярные сегодня клоны Unix (FreeBSD, Linux), и формально далекие от нее системы (Windows). Все они воссоздают одну и ту же модель программа-процесс-файл. И кажется уже, что эта модель неизбежна, что она чуть ли не дана нам свыше, как законы физики, а подвергать ее сомнению — кощунственно. Но тем не менее попробуем.

UNIX: 40 лет спустя

Сорок лет для одной технологии довольно много, однако ОС Unix сумела перешагнуть этот рубеж. Почему?

Для начала напомним, какие задачи вообще решает ОС. Обычно считается, что операционная система предназначена для запуска программ, что неверно: для запуска программы достаточно примитивного монитора размером 10 Кбайт. Второе распространенное мнение — операционная система отвечает за управление оборудованием. Это и правда, и неправда. Во-первых, управление оборудованием можно упаковать в библиотеку подпрограмм, как до появления ОС и делали. Во-вторых, нередко программы исключают ОС из цепочки доступа к оборудованию, и, наконец, такие вещи, как стек протоколов TCP/IP, не могут быть описаны как «управление оборудованием» — задачи и возможности TCP/IP выходят за пределы этого определения. Выходят за рамки управления оборудованием и такие функции, как тайминг, синхронизация, межпроцессное взаимодействие и другие не связанные напрямую с аппаратурой функции ОС.

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

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

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

Что именно в операционной системе влияет на удобство работы? Ответ и прост и сложен одновременно. Если посмотреть на историю индустрии разработки ПО, то выяснится, что основной прогресс происходит по пути от монолитных программ (все от начала и до конца сделал сам разработчик) к модульности (разработчик создал только уникальный код программы, а все готовое «взял с полки»). Сама ОС предоставляет программисту компоненты, а средства динамической компоновки позволяют подключать к программам готовые модули. Изначально это были статические библиотеки (программист должен принять решение, и результат будет намертво забетонирован в программу), затем библиотеки динамические (использованную библиотеку можно обновить, но суть выполняемой ею функции неизменна) и, наконец, динамическая компоновка решений силами пользователя из «кубиков» (IPC, DDE, OLE, SOAP и т. п.).

Удачный шаг в направлении последнего подхода был сделан в Unix, когда было введено правило «все утилиты обрабатывают текстовый файл» и позволено комбинировать утилиты с помощью shell-скриптов и пайпов. Но в современном объектном мире планарный текстовый файл стал анахронизмом, скрипты перестали соответствовать требованиям времени. Кто их заменил? Никто. В результате ОС современности деградировали по сравнению с Unix конца XX века — они не предоставляют пользователю внятных средств комбинирования готовых функциональных блоков, да и для программиста их возможности не так уж и привлекательны — и в силу исторических наслоений, превративших некогда стройные API в кучи фрагментированных малосовместимых, нерегулярных функций, и в силу того, что сами основы, на которых зиждется сегодняшняя ОС, вовсе не так уж удачны.

Старые основы

Рассмотрим несколько основополагающих сущностей традиционных операционных систем.

Процессы

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

Можно ли предложить что-то более удобное, чем процесс? Если применять современные технологии компиляции Just in Time или верификации кода, вполне реально гарантировать защиту без разделения на отдельные адресные пространства, причем защиту куда более детальную — каждый мельчайший объект программы будет защищен от каждого другого! Такая защита дешевле, чем процессы (верификация или компиляция делается один раз, а адресные пространства требуют постоянного, сотни раз в секунду, переключения контекста), а качество обеспечивает куда более высокое.

Технологические особенности ОС "Фантом"

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

Практически ядро выполняет мгновенный снимок с помощью следующей серии операций:

  1. Вынуждает страницы, не имеющие актуальной копии на диске, таковую создать, что снижает суммарную эффективность процесса (часть из них после записи на диск тут же окажутся “грязными” снова и потребуют повторной записи), но зато позволяет процедуре мгновенного снимка пройти мягче и получить в итоге более позднюю копию состояния. В частности, здесь обеспечивается определенный запас легко освобождаемой физической памяти для фазы 3.
  2. Все нити останавливаются, и все страницы памяти помечаются как read only. Нити продолжают работу. Фактически, это и есть мгновенный снимок. Длительность этой операции меньше, чем задержка работы нити вследствие обычного переключения процессора на другой процесс.
  3. Дальнейший процесс идет параллельно двумя путями. Во-первых, при попытке обращения к странице на запись создается ее копия, которая остается в рабочем множестве процесса (и доступна для записи) – она уже попадет только в следующий мгновенный снимок. Старая будет со временем записана на диск и освобождена. Во-вторых, процесс подготовки мгновенного снимка обходит все страницы по очереди и выполняет финализацию снимка. Страница может быть в трех состояниях:
  • старая (не менявшаяся с прошлого мгновенного снимка) страница или страница, записанная на этапе 1 и не успевшая с тех пор измениться, не требует никаких действий (таких страниц большинство);
  • страница, которая попыталась измениться и была скопирована, — для нее выполняется запись старой копии страницы, после чего старая копия освобождается;
  • страница, которая менялась со времени предыдущего мгновенного снимка, но не менялась с фазы 2, просто записывается на диск.

Объектная среда. Система представляет собой виртуальную машину, работающую в персистентной виртуальной памяти. Виртуальная машина — это классическая стековая (объектный и целочисленный стеки) машина, не идентичная JVM, но достаточно близкая к ней. Отличия вызваны более жесткими требованиями к защите – традиционные виртуальные машины спроектированы для работы внутри процесса и не отвечают потребностям среды, в которой в одном адресном пространстве живут классы и объекты разных пользователей. В частности, виртуальная машина "Фантом" бескомпромиссна в отношении типов, и, например, integer — это такой же класс, как и остальные. Это, например, облегчает реализацию чистой виртуальной машины, гарантирующей невозможность создания пользователем произвольного указателя и сканирования памяти. Соответственно, никаких небезопасных расширений в системе нет и не планируется.

Unix-подсистема. Подсистема предоставляет универсальный механизм, в рамках которого можно создавать модули ядра (в том числе драйверы), исполнять прикладной код в приближенной к POSIX среде и реализовывать родные для объектной среды расширения. Все три вида программ могут пользоваться системными вызовами POSIX и работают в отдельном адресном пространстве. В рамках Unix-подсистемы предоставляются традиционный файловый API и доступ к объектной среде.

Файлы

Посягательство на столь привычную вещь, как файл , вызывает у программистов, как правило, реакцию, близкую к возмущению: ну файл-то, знакомый и родной, чем не угодил? Столько лет, верой и правдой! Вот в вере-то все и дело — файл слишком доверчив. Будучи пассивной сущностью, он не может себя защитить: если уж программа получила к нему доступ, она вольна куролесить как угодно. Если заменить файл на объект (некоторые современные ОС уже двигаются в этом направлении), то вольность может быть ограничена — методы объекта обеспечат только допустимые операции как с точки зрения сохранения целостности данных, так и с точки зрения прав доступа. Объект уже нельзя открыть не той программой, испортив данные, да и вирусу не будет позволено гулять по битам и байтам.

От этой модели всего один шаг до еще более простой. А что если избавить программу вообще от операции сохранения на диск? Ведь необходимость в такой операции диктуется всего лишь старомодностью нынешних ОС. Достаточно обеспечить программе сохранение ее состояния прозрачным образом, и она перестанет нуждаться в том, чтобы записывать свое состояние в файл. Это снимет с разработчика немалую часть объема работы и упростит жизнь пользователю, теперь после перезагрузки компьютера уже не надо вновь открывать закрывшиеся окна, да и внезапное отключение электричества не лишит вас результатов работы. Для этого нужно, чтобы операционная система могла создать для программ персистентную среду — видимость, что никакой перезагрузки ОС не происходило. На первый взгляд это очень «дорогая» задача: кажется, что для достижения этой цели нужно то и дело записывать на диск всю память компьютера. Однако на практике это не так, и существуют способы обеспечить очень частое «фотографирование» памяти при относительно скромных объемах ввода/вывода. Это обеспечивается умеренной модификацией системы виртуальной памяти, которая является основой любой современной ОС.

Персистентность на первый взгляд похожа на функцию hibernate традиционных ОС, но на практике сильно от нее отличается: hibernate выполняется вручную, не может осуществляться параллельно с нормальной работой программ (требует остановки всего), довольно ресурсоемка и вовсе не гарантирует восстановления системы после выключения. Персистентная ОС, напротив, автоматически выполняет «фотографирование» своего состояния, делает это часто, не останавливает при этом работы и гарантирует, что хотя бы одна целостная «фотография» всегда существует. Надо отметить, что проблемой здесь является создание целостного (логически содержащего состояние всех объектов ОС на один момент времени) снимка, причем без останова программ. Представим себе бегуна на стадионе — остановить его нельзя, но нужно сфотографировать, причем так, чтобы и спортсмен, и стадион выглядели резко, а выдержка составляла несколько минут. Кажется, что это невозможно, но практически задача вполне решаема, и даже не столь уж сложным способом.

Простота в деталях

Может сложится впечатление, что "Фантом" достаточно сложная ОС, сложнее, чем UNIX, однако предлагаемая в ней парадигма упрощает и прикладной код, и саму систему. Для того, чтобы поработать с документом программа в классической операционной системе читает файл в память, десериализует (форимрует естественное для программы состояние), а иногда и декомпрессирует его, строит в памяти его бинарное представление (как правило — это граф объектов), инициализирует компоненты визуализации и бизнес-логики, выполняет необходимые изменения, а затем производит все эти действия в обратном порядке. При этом десериализованное представление хранится в виртуальной памяти, которая уже предоставляет все нужные механизмы для эффективного сохранения данных на диск.

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

 

Схема работы приложений в традиционной ОС

Соотношение затрат на доступ к документу в ОС "Фантом" и традиционной ОС в пользу первой (в ОС "Фантом" остается только три центральных блока: граф, обработка страниц и страничная подкачка), а, например, доступ к части документа для ОС "Фантом" — это один страничный отказ и его обработка, что означает исполнение сотен или тысяч инструкций процессора и прямую доставку требуемого фрагмента документа с диска в память программы. Данные документа при этом вообще не обрабатываются — ядро только обеспечивает обслуживание операции ввода-вывода, не прикасаясь к пользовательским данным. Аналогичный процесс в традиционной ОС — это миллионы инструкций, очередь перемещений и обработок данных документа.

 

ОС "Фантом"

Итак, современные операционные системы не отвечают требованиям жизни, причем устроены так не потому, что это оптимально, а в силу привычки. Проект "Фантом" преследовал амбициозные цели — с одной стороны, спроектировать ОС, которая была бы сделана с чистого листа и решала реальные задачи наиболее оптимальным образом, а с другой — была бы совместима с существующим прикладным программным кодом.

Программная модель

ОС "Фантом" базируется на простой модели программирования. ОС представляет собой персистентную объектную среду — примерно аналогичную тому, как если бы был запущен и гарантированно никогда не останавливался сервер приложений для объектного языка программирования. При этом саму ОС можно останавливать и перезапускать, внезапно выключать компьютер – с точки зрения программы это будут всего лишь паузы в работе.

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

  • прикладные документы-объекты не требуют сохранения на диск — система гарантирует существование объекта, пока на него имеется хотя бы одна ссылка;
  • программы могут активно и глубоко взаимодействовать — общее адресное пространство системы позволяет напрямую, без специальной помощи ОС, общаться двум совершенно «незнакомым» программам, а эффективность такого взаимодействия превосходит эффективность традиционных средств межпрограммной коммуникации (очереди, пайпы), причем оно удобнее, чем взаимодействие через обычную разделяемую память (нет опасности, что указатель из разделяемого участка «смотрит» за его пределы, есть гарантия того, что между «запусками» адреса памяти не изменятся);
  • обеспечивается защита доступа к данным с точностью до объекта — каждый мельчайший объект в системе защищен от посягательств со стороны любого другого объекта, изменить состояние объекта можно только посредством вызова метода, причем добраться до него может лишь тот, кому явно выдали указатель на объект, а сканирование памяти невозможно;
  • в силу того, что документы и компоненты никогда не покидают адресное пространство ОС, между ними возможны долговременные связи посредством обычного указателя, а это означает, что под ОС "Фантом" можно, например, написать такую реализацию Photoshop, которой не нужно будет тратить минуты, чтобы при старте найти по сусекам все свои плагины, профили и шрифты.

Для полноценного использования ресурсов компьютера ОС "Фантом" требует 64-разрядного адресного пространства, но возможна работа и в 32-разрядном.

Совместимость

ОС "Фантом" — объектная операционная среда, поэтому планируется организация совместимости с языками программирования, которые уже генерируют код для виртуальной машины Java. В дальнейшем будет реализована совместимость и с виртуальной машиной CLR (.NET). При этом никакого ограничения на парадигму самого языка программирования не накладывается: императивный, логический, функциональный язык. Для последних реализована оптимизация хвостовой рекурсии и сделана поддержка замыканий на уровне виртуальной машины "Фантом".

Поддержка разработки на языках типа Си с адресной арифметикой в рамках основной объектной среды "Фантом" не планируется, но для миграции программ, разработанных на устаревших языках программирования, реализована среда эмуляции, предоставляющая основные интерфейсы ядра Unix. Эта среда, в основном, предназначена для реализации таких компонентов ОС, как кодеки, конвертеры и процессоры потоковых данных большого объема — программных модулей, для которых персистентная модель не очень ценна (или даже вредна), а существующая реализация разработана на Си, C++ или других языках пакета GCC. Unix-подсистема является дополнительной и отключаемой, ОС функционирует и без нее. В дальнейшем возможно реализовать персистентную Unix-подсистему, но нет уверенности в том, что она будет востребована.

Текущий статус проекта

Сегодня ОС "Фантом" существует в виде прототипа, демонстрирующего основные свойства концепции, но пока не реализующего всех запланированных возможностей. Система работает как в эмуляторе, так и на реальной аппаратуре (x86, 32-разрядная адресация), запускает тестовые прикладные программы, выполняет мгновенные снимки (snapshot) состояния и рестарт с последнего доступного снимка при внезапной перезагрузке, содержит базовые драйверы графической системы, минимальную реализацию OpenGL, поддерживает протоколы TCP/IP.

Код системы лицензионно чист и на 90% разработан с нуля, без применения чужих наработок. В готовом виде использованы только код библиотеки Си и реализация стека TCP/IP (ядро ОС).

Основные проблемы

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

Глобальная сборка мусора

Будучи весьма масштабной объектной средой, "Фантом", естественно, требует алгоритма сбора мусора. При этом размеры объектной среды системы имеют порядок, соответствующий размеру типичного жесткого диска, то есть на сегодня — 1 Тбайт. Очевидно, что в недалеком будущем надо говорить о масштабе в 10, 100 Тбайт и 1 Пбайт. Сборка мусора на объеме в 1 Тбайт при условии, что реально 95% данных лежат на диске, весьма затратная работа, и процесс может растянуться на сутки. При этом сборщик может оказать огромное давление на подсистему виртуальной памяти и повлиять на работу обычных программ, а обеспечение параллельной с работой программ сборки мусора создаст ощутимую нагрузку на систему. Поэтому было принято решение разбить сборку мусора на две части — быстрый негарантированный алгоритм (refcount, собирает мусор сразу, но не в состоянии победить циклы) и длинный полноценный алгоритм, не затрагивающий актуальную копию системы, а работающий на снимке ее состояния. Идея в том, что, имея снимок состояния памяти ОС, можно провести в ней сборку мусора, и правомерно утверждать, что объект, являющийся мусором на снимке, будет мусором и в более позднем состоянии памяти, так как, по определению, попадание объекта в статус мусора необратимо.

Краевые объекты и информирование о рестарте

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

Сама по себе задача информирования объектов о рестарте тривиальна, но важно, чтобы такое информирование произошло до реального старта системы, и произошло таким образом, чтобы прикладной код не мог ни проигнорировать сообщение о рестарте (если нельзя скрыть этот факт), ни получить его раньше, чем система реально стартовала. На практике это реализовано следующим образом: среди всех объектов среды выделяются так называемые «краевые», то есть взаимодействующие с оборудованием объекты. Эти объекты, в частности, отличаются тем, что реализация их методов скрыта в ядре ОС. При рестарте системы такие объекты до запуска прикладных нитей получают сообщение о рестарте внутри кода ядра, и, если таковое сообщение требуется транслировать на прикладной уровень, генерируют для всех заблокированных внутри себя нитей специальное исключение. Фактически исключение не распространяется до момента актуального запуска нити, внутри которой произошел заблокированный вызов метода краевого объекта. Иначе говоря, де-факто исключение не генерируется — вместо этого нить разблокируется и переносится на начало метода, код которого и порождает необходимое исключение. Такой подход гарантирует, что сообщение о рестарте краевого объекта нельзя проигнорировать (как минимум — если исключение не будет поймано — нить перестанет исполняться), и все такие исключения реально доставляются в момент, когда система уже работает. Естественно, если краевой объект признал себя после рестарта неработоспособным (например, соответствующее ему оборудование отказало или было удалено из компьютера), то все последующие обращения к нему вызовут исключение тоже.

Прикладное значение ОС

Операционная система "Фантом" имеет не только академическое, но и прикладное значение. Система обеспечивает низкую стоимость разработки приложений и высокую надежность при их эксплуатации. Модель ОС гарантирует приложениям сохранение их состояния и восстановление его при рестарте системы, а это означает, что после отказа питания компьютер, во-первых, очень быстро загрузится, а во-вторых, продолжит работу с момента последнего «снимка». Для критичных областей применения снимок можно делать достаточно часто. Несколько примеров ситуаций, в которых это свойство весьма полезно:

  • банковские системы — отказ аппаратуры не приводит к длительным операциям по восстановлению базы данных, операторы продолжают прерванные сеансы с того же самого места;
  • медицинское оборудование — краткий сбой в питании системы искусственного дыхания в случае традиционной ОС требует двухминутного процесса перезагрузки и перезапуска программ, что может привести к смерти пациента;
  • системы пожарной безопасности и сигнализации после отказа электропитания начинают длительный опрос датчиков и процедуру реинициализации, а ОС "Фантом" позволяет обойтись без нее, и, кроме того, сохранить «знания» прикладной программы об актуальном состоянии системы.

Проект дошел до стадии реализации прототипа и движется в сторону тестовых прикладных применений системы.

Дмитрий Завалишин (dz@dz.ru) — генеральный директор компании Digital Zone (Москва).