Проект «Neutrino»: В поисках Святого Грааля

© И. Н. Коваленко, 1997


QNX и Unix - краткий обзор различий Цели проекта Neutrino.
Архитектура микроядра Neutrino Объекты и сервис микроядра Практические аспекты применения системы Заключение

Прошло несколько лет с момента появления первых 32-битных операционных систем для процессоров Intel. Когда это произошло, было много спекуляций о том, какая из них станет «основной» и затмит все отальные. И что-же? Windows95 занимает первую строчку в рейтингах продавцов, но ее ограниченность общеизвестна. Windows NT увеличила свою популярность и многие пытаются использовать ее как единую ОС для всех задач, но это далеко не всегда оправдано. OS/2 так-же сделала заметный рывок и начал выделяться лидер в мире Unix - Linux. Тем не менее, ни одна из этих систем по прежнему не способна справляться с задачами промышленной автоматизации, рынок которых в последние годы быстро растет. Причина, на мой взгляд, заключается в том, что большинство систем страдает одним общим недостатком - неэффективный дизайн, из-за которого мощность новых процессоров расходуется в значительной степени на новую более «раздутую» ОС, большая часть функций которой не нужна в каждом конкретном случае.

Два года назад я писал статью о системе QNX, которая быстро развивалась, превращаясь из узко специализированной ОС для систем реального времени в более-менее универсальную систему. Однако ее разработчики отказались от попыток «добавить еще одну функцию» в QNX, поскольку этот путь ведет в тупик. Никому не нужна еще одна эклектичная система, отягощенная грузом устаревших решений. Еще до появления Windows95, был начат новый проект, целью которого было создание совершенно новой ОС, которая, не наследуя устаревшую кодовую базу, могла бы воплотить в себе лучшие идеи, разработанные в теории операционных систем. Этот проект получил кодовое название «Neutrino», которое довольно удачно отражает его суть – неуловимо маленькая и очень быстрая ОС. Данная статья являетя попыткой ответа на вопрос «Что такое Neutrino?» и, что более интересно, почему она была создана и в чем ее отличия от QNX.

QNX и Unix - краткий обзор различий

Прежде всего, Neutrino, как и QNX, по своему «духу» попадают в категорию Unix-подобных систем, несмотря на все фундаментальные различия. Поэтому лучший способ понять особенности каждой системы – сравнить их. Для начала небольшой обзор различий между QNX и Unix, для тех кто не знаком с QNX. Впрочем, это сравнение может быть полезным и тем, кто с ней уже знаком.

Что такое QNX?

С точки зрения пользовательского интерфейса и API, это ОС очень похожая на UNIX. Если Вы пользователь, знакомый с UNIX, то вероятно сможете работать с ней без проблем, так так в ней присутствует практически весь набор стандартных утилит и сохраняется большая часть семантики. X Window конечно тоже есть, как и TCP/IP. Если Вы программист, знакомый с UNIX, то для Вас не составит большого труда перенести Ваши или GNU/Free приложения в QNX. Такие приложения как Apache и Mosaic хорошо демонстрируют степень совместимости API.

Однако, QNX это не версия UNIX. Она была разработана с нуля и построена на совершенно других архитектурных принципах, но с учетом группы стандартов POSIX, которые возникли в результате обобщения существующей практики в различных версиях системы Unix. Разработка ведется канадской фирмой QNX Software Systems Limited (далее - QSSL).

Чем QNX отличается от UNIX?

QNX была первой коммерческой ОС, построенной на принципах микроядра и обмена сообщениями. Система реализована в виде совокупности независимых (но взаимодействующих через обмен сообщениями) процессов различного уровня (менеджеры и драйверы), каждый из которых реализует определенный вид сервиса. Эти идеи позволили добиться нескольких важнейших преимуществ: Конечно, у всех медалей по две стороны. Поскольку QNX не базируется на ядре UNIX, не следует ожидать бинарной совместимости. Есть и некоторые ограничения, связанные с ориентацией системы на рынок встроенных систем реального времени. Вот важнейшие из них:   Хотя этот список содержит достаточно важные пункты, не все они являются критическими для рынка QNX, поскольку она не проектировалась для конкуренции с Unix. Но, что гораздо более важно, некоторые пункты этого списка, а также некоторые другие ограничения QNX, являются серьезными недостатками с точки зрения теории систем реального времени. И это притом, что QNX является лидером этого рынка!

QNX и системы реального времени

Что-же это за недостатки? Для того, чтобы это понять, полезно определить требования к ОС, предназначенной для реализации систем реального времени. Именно этот смысл я вкладываю в общеупотребительный термин «ОС реального времени» (Real Time OS). Использование какой-либо ОС еще не гарантирует получения результата. Можно взять любую ОС такого типа и создать на ее базе некую систему, предназначенную для работы в реальном времени (далее – «система реального времени»), но не способную на это фактически. Чем характеризуется система реального времени? Есть два основных требования: Для выполнения этого требования система должна обладать предсказуемостью, которую не следует путать с производительностью. Никакой процессор не сделает Windows 3.1 предсказуемой. Для выполнения этого требования система должна обладать естественным параллелизмом. Практически это означает, что система должна поддерживать вытесняющую многозадачность, основанную на приоритетах, а также быть способной использовать нескольно процессоров одновременно.В то-же время, можно взять некоторую ОС и на ее основе создать систему реального времени. При условии, что такая ОС отвечает по крайней мере следующим требованиям:
  1. ОС должна поддерживать вытесняющую многопоточность (preemptive multi-threading) и мультипроцессорные архитектуры;
  2. Аппаратная архитектура должна поддерживать несколько уровней прерываний (interrupt levels) а ОС должна обеспечивать вытеснение (preemption) обработчиков прерываний;
  3. Каждая нить управления (thread) должна иметь способ выражения собственной важности. В идеале планировщик должен предоставлять процессор той нити, у которой осталось меньше всего времени до исчерпания ее временных рамок (алгоритм, известный как EDF – Earliest Deadline First). Однако, учитывая сложность реализации такой схемы, можно считать достаточным наличие приоритетов у нитей, при условии поддержки достаточно большого количества уровней приоритетов;
  4. ОС должна обеспечивать предсказуемые механизмы для синхронизации между нитями и взаимодействия процессов, разрешающие проблему «инверсии приоритетов». Это означает, что как при передаче данных, так и при синхронизации нитей должно обеспечиваться «наследование приоритетов».
  5. Поведение самой ОС после системных вызовов и наступления событий должно быть предсказуемо и известно заранее. Это означает, что разработчики ОС должны специфицировать такие временные характеристики, как «задержка обработки прерывания» (interrupt latency), максимальное время маскировки прерываний а также максимальное время исполнения всех системных вызовов.
  6. ОС должна быть способна работать в ограниченных ресурсах, особенно это касается оперативной памяти;
  7. Стоимость системы при массовых тиражах должна быть достаточно низкой;
  8. ОС должна обеспечивать API и нижележащий сервис, соответствующий по структуре и реализации требованиям систем реального времени;
Немногие ОС способны выполнить хотя-бы часть этих требований, хотя не все из них одинаково важны. Например Windows NT, несмотря на ее более совершенную, по сравнению с Windows 95, архитектуру совершенно не соответствует критическим требованиям 2 и 4 , а также очень плохо соответствует требованиям 3, 5, 6, 7 и 8. Заметим однако, что QNX также не вполне отвечает всем требованиям. В частности, QNX имеет следующие серьезные недостатки: В некоторой степени некоторые из указанных недостатков компенсируются достоинствами QNX. Например, практическое отсутствие нитей и SMP отчасти компенсируется очень малым временем переключения контекста между процессами, а высокие цены – возможностью модульного лицензирования. Семафоры же вообще являются пятым колесом в телеге для QNX.

Тем не менее, глядя в будущее, такую ситуацию нельзя признать удовлетворительной. По этим причинам и был в свое время начаты проекты Neutrino и Photon, призванные в конечном итоге образовать тандем, решающий все нынешние проблемы.

Цели проекта Neutrino.

Если попытаться обобщить все проблемы QNX, то их можно коротко выразить 3 пунктами:
  1. Недостаточная согласованность с требованиями POSIX к системам реального времени;
  2. Невозможность применения на встроенных системах с ресурсами 64K – 512K;
  3. Невозможность применения на системах высшего уровня (SMP серверах).
Отсюда видно, что глобальная цель проекта Neutrino - создание POSIX совместимой масштабируемой ОС, пригодной для построения систем реального времени на самом широком спектре оборудования.

При этом была также поставлена цель добиться независимости кода приложений от характера целевой системы. То есть, код для «тостера» должен быть бинарно совместим с кодом для SMP-сервера. Система такого рода должна быть настолько гибкой, эффективной и универсальной, что о Neutrino стали говорить как о «Святом Граале» операционных систем.


Рис. 1 - Область применения Neutrino

Однако, общая формулировка цели нуждается в уточнениях. Во-первых – почему ОС должна быть POSIX совместимой? На это есть множество причин, приведем лишь некоторые из них:

Впрочем, POSIX это большая группа стандартов, а термин «Neutrino», если говорить конкретно, применяется на данном этапе не ко всей ОС, а лишь к ее микроядру. Это микроядро будет совместимо, в частности, со следующими стандартами POSIX: Кроме того, в микроядро Neutrino разрабатывалось с учетом некоторых других требований, таких например, как поддержка твердотельных дисков и возможности исполнения кода непосредственно из ROM.

Архитектура микроядра Neutrino

Указанные выше цели гораздо легче продекларировать, чем достичь. Например, идея реализации ОС дла систем реального времени с интерфейсом POSIX существует давно, но никому этого пока не удавалось сделать. POSIX-системы имеют репутацию «раздутых», поскольку они ассоциируются в первую очередь с Unix. В некотором смысле, Neutrino является доказательством возможности существования компактной POSIX системы.

Для достижения этих целей недостаточно было просто косметической модернизации микроядра QNX. Neutrino представляет собой значительно более совершенную модель, выполняющую гораздо больше функций, чем микроядро QNX, имея при этом лучшую производительность и временные характеристики. Улучшенное микроядро позволило также вчетверо уменьшить размер менеджера процессов (с 80 до 20Kb), уменьшив таким образом их суммарный размер почти вдвое.

Микроядро и наноядро

Очевидно, расширение функций привело в увеличению размера микроядра, с 10Kb до 28Kb. Однако, его содержимое теперь лучше структурировано. Фактически, в нем выделилось «надоядро», обеспечивающее поддержку фундаментальных объектов микроядра, которое, в свою очередь, поддерживает базовый сервис для пользовательских нитей и дополнительных системных модулей.

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

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


Рис. 2 - Сервис микроядра и объекты наноядра

Все системные вызовы Neutrino могут вытесняться, при необходимости обработать вызов от нити с более высоким приритетом, даже в процессе передачи сообщений. Это качество микроядра, а также его сравнительная простота и малый размер, позволяют минимизировать невытесняемые последовательности кода в системе. Это, в свою очередь, имеет несколько положительных следствий. За счет этого улучшаются временные характеристики системы. Скромные требования к памяти упрощают разработку встроенных систем низшего уровня. Наконец, это уменьшает количество блокировок в коде (spin-locks), необходимых для поддержки мультипроцессорных архитектур, что упрощает реализацию SMP и повышает эффективность использования дополнительных процессоров. То есть, улучшаются также характеристики ОС, необходимые для построения систем высокого уровня.


Рис. 3 - Кластерная система на основе SMP Neutrino

По заявлениям QSSL, бета тестирование SMP Neutrino продемонстрировало близкий к линейному (!) рост производительности при добавлении дополнительных процессоров (до 8), при автоматической балансировке нагрузки. Скептики скажут, что это невозможно, но они всегда это говорят J . Многое в QNX и Neutrino «невозможно». Кроме того, реализация SMP Neutrino допускает ручное распределение процессов между процессорами, что позволит добиться еще большей эффективности в контролируемой среде исполнения. Эта система уже вызвала большой интерес со стороны телекоммуникационных компаний, нуждающихся в сверхпроизводительных системах для реализации мощных коммутационных систем. Один из проектов в этой области с использованием Neutrino уже начат.

Микроядро и дополнительные модули

Главное видимое отличие микроядра Neutrino от микроядра QNX – это его соотношение с внешними модулями. В QNX микроядро физически существовало в коде менеджера процессов, что означало необходимость использования последнего даже там, где не нужны его функции. Поскольку Neutrino должна быть применима для систем самого низкого уровня, типа «интеллектуального тостера», это ограничение необходимо было ликвидировать, с целью снижения требований к памяти. Микроядро Neutrino может существовать вне менеджера процессов, что позволяет связать его с пользовательским кодом, получив таким образом сущность, называемую «системный процесс» (system process). Такой процесс не требует для работы ни ОС, ни даже BIOS, поскольку в комплект системы входит набор модулей IPL (начальной загрузки), способных заменить BIOS в этом качестве.

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


Рис. 4 - Формирование приложения Neutrino

Если же для системы нужна полноценная ОС, нужно связать микроядро с менеджером процессов Neutrino (ProcNto), затем сформировать шаблон ядра, и получить из него загружаемый двоичный образ так-же как это делается в QNX.

А что, если для реализации некоторой системы ProcNto не подходит? Neutrino предоставляет разработчикам целый спектр решений на этот случай.

Альтернативная реализация дополнительного сервиса

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

Расширения ядра и добавление новых системных вызовов

Еще одно новшество микроядра Neutrino заключается в поддержке расширенийxtensions). Код Neutrino содержит различные таблицы переходов, которые могут быть переопределены в момент исполнения любой нитью, работающей в адресном пространстве микроядра. Эти таблицы могут указывать на адреса функций в любой другой нити. Например, ProcNto использует этот механизм для замены примитивных функций управления памятью, содержащихся в Neutrino, на более сложные, позволяющие выполнять операции с множественными виртуальными адресными пространствами, соответсвтующими различным процессам. Само микроядро не содержит кода, способного работать с виртуальной памятью, чтобы не обременять системы, которые этот механизм не поддерживают или не используют.

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

Neutrino также содержит специальную точку входа, через которую нити, исполняющиеся в адресном пространстве микроядра, могут передавать ему адреса функций. Затем микроядро вызывает эти функции со своим контекстом. Этот механизм используется менеджерами сети для того, чтобы выполнять манипуляции объектами микроядер на различных узлах от их собственного имени. Именно это позволяет добиться полной прозрачности сетевого взаимодействия в QNX/Neutrino, поскольку исчезает разница между локальным и удаленным исполнением программы. Сеть Neutrino превращается в «виртуальный компьютер», позволяя создавать высокопроизводительные кластерные SMP системы.

Наконец, привилегированные нити могут определять и регистрировать в микроядре новые системные вызовы, расширяя его функциональные возможности.

Управление процессами и памятью

Как было показано выше, управление процессами и памятью не является, строго говоря, функцией Neutrino. Это функция менеджера процессов ProcNto, который кроме этого, занимается поддержкой пространства имен ввода/вывода и еще рядом "мелочей". Однако этот обзор был бы неполным без рассмотрения данного вопроса.

Прежде чем управлять процессами, необходимо иметь возможность загружать их с какого-либо носителя. С этой целью в состав ProcNto также вхоят «нить заргузчика» и «нить терминатора». Нить загрузчика обеспечивает загрузку исполняемых модулей в формате ELF, QNX4 и shell-скриптов. Формат ELF (известный также как Evil Linkage Format J ) является для Neutrino стандартным, поскольку он обеспечивает ряд преимуществ, таких как поддержка динамического связывания и, что очень важно для встроенных систем, совместим со спецификацией XIP (eXecute-In-Place), предусматривающей исполнение кода прямо из ROM, без загрузки в RAM. Нить терминатора обеспечивает «уборку мусора» после завершения процессов, на тот случай если они не смогли сделать это сами.

Еще одна из функций ProcNto это поддержка виртуальной файловой системы, встраиваемой в двоичный загружаемый образ системы. Для встраиваемых систем, не требующих хранения данных, этот вариант очень привлекателен, поскольку он упрощает структуру системы, снижает требования к памяти и стоимость лицензии.

И все-же, самое интересное это управление памятью. Этот вопрос является достаточно болезненным, поскольку от его решения зависит очень многое. Решение, примененное в QNX не было достаточно гибким. QNX 4.23 всегда использует виртуальную память, что не позволяет использовать ее на некоторых типах Intel-совместимых процессоров, довольно широко применяемых во встроенных сиcтемах, например производства National Semiconductor или AMD, поскольку они не содержат Paged-MMU (устройство управления виртуальной памятью). Кроме того, зависимость микроядра от специфичной для x86 аппаратуры MMU затрудняет перенос системы на другие платформы.

В результате, Neutrino использует соломоново решение – предоставить выбор модели защиты памяти разработчикам. Код Neutrino не использует MMU или виртуальную память в явном виде. Это достигается за счет выноса функции инициализации MMU во внешний модуль (mmuon) и выносе функций управления виртуальной памятью в расширения микроядра, обеспечиваемые ProcNto. Для поддржки MMU модуль mmuon нужно включить в ядро, после чего менеджер процессов сможет поддерживать виртуальную память. Этот модуль не является «сервером», он выполняет инициализацию процессора и немедленно завершает свою работу. Сам менеджер процессов также существует в нескольких вариантах, соответсвуюющих типу защиты памяти. Таким образом, Neutrino/ProcNto поддерживает 4 варианта управления памятью, от полного отсутствия защиты, до предоставления каждому процессу собственного 4Gb виртуального адресного пространства. В будущем появится также версия ProcNto, поддерживающая своппинг виртуальной памяти на диск, что может оказаться желательным для некоторых систем верхнего уровня.

Вариант 1: Физическая память.

Все нити перемещаются при построении системы в адреса, расположенные в адресном пространстве Neutrino. Менеджер процессов обычно отсутствует. Это типичная конфигурация, которую предоставляют различные realtime executive, но отличие Neutrino в том, что она пытается даже в этой модели памяти выполнять (насколько это возможно) функцию mmap(), что позволяет обходиться без изменения исходного кода системы при смене модели памяти.

Вариант 2: Защита «системных» нитей от пользовательских.

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


Рис. 5 - Минимальная модель защиты памяти

Вариант 3: Защита всех нитей друг от друга.

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


Рис. 6 - Модель защиты памяти без виртуализации

Вариант 4: Виртуальная память.

В этой модели каждый процесс имеет собственное адресное пространство, начинающееся с адреса 0 и защищенное от остальных процессов. Нити процесса делят с ним одно адресное пространство. Системное адресное пространство Neutrino также защищено от остальных процессов. Защита поддерживается аппаратурой Paged-MMU и реализуется соответствующей версией ProcNto.


Рис. 7 - Модель защиты на основе виртуальной памяти

Объекты и сервис микроядра

Neutrino поддерживает 48 системных вызовов (по сравнению с 14 в QNX), обеспечивающих нити, передачу сообщений, сигналы, системные часы и таймеры, обработку прерываний и механизмы синхронизации нитей.

Процессы и нити: Диспетчеризация и Синхронизация

Neutrino поддерживает модель нитей POSIX 1003.1с, в соответствии с которой процесс может динамически создавать и уничтожать одну или более нитей. Разработчики могут по своему выбору использовать для работы с нитями либо API Neutrino, либо стандартную библиотеку pthreads.

Этот же стандарт определяет, что нити должны иметь собственные уровни приоритетов. Neutrino, к моменту выхода окончательной версии, будет поддерживать 256 уровней, причем каждая нить может также иметь собственный алгоритм диспетчеризации, список которых традиционен для QNX (и определен POSIX) – round-robin, FIFO и адаптивный.

Разумеется, поддержка нитей подразумевает также, что они могут делить общие данные. Для обеспечения синхронизации Neutrino поддерживает два механизма: условные переменные (condvars) и блоки взаимного исключения (mutexes). Для этих объектов микроядро поддерживает механизм наследования приоритетов.

Реализация mutexes отличается очень высокой эффективностью. Получение или освобождение несвязанного объекта типа mutex требует выполнения всего одного кода. Для сравнения, в Windows NT эта операция может занимать время до 700 ms.

Модель событий и средства обмена сообщениями

Модель событий Neutrino представляет собой еще одно значительное достижение этой системы. Учитывая сложность и многообразие форм событий и способов уведомления о них, реализация такой системы в каждой паре «клиент-сервер» может занять значительный объем кода и затруднить разработку надежной модели взаимодействия. Поэтому Neutrino использует другой подход, называемый event steering, при котором сервер может передать микроядру форму уведомления клиента, которую он у него запросил.

Практически, нити получают уведомления от одного из трех типов источников: сообщение от другой нити, прерывание или таймер. События существуют в форме синхронных сообщений, асинхронных пульсов, Unix или POSIX сигналов, прерываний а также специального события ForceReady, вызывающего безусловный переход нити в состояние Ready, без доставки ему какого-либо события. Механизм event steering работает следующим образом:

  1. клиент посылает серверу сообщение, содержащее структуру с описанием желаемого механизма уведомления;
  2. сервер регистрирует эту форму в микроядре и отвечает клиенту, выводя его из блокировки.
  3. Когда возникает необходимость в уведомлении клиента, сервер посылает ему сообщение, а микроядро транслирует его в заказанную форму.

Рис. 8 - Унифицированная модель событий

Сигналы в Neutrino поддерживаются в двух разновидностях: классические сигналы Unix и реалтаймовые сигналы POSIX, c которыми можно передавать короткую порцию данных (4 байта). Другое различие между ними заключается в том, что сигналы POSIX при поступлении к процессу буферизуются, пока какая-либо из нитей процесса не проявит к ним интерес. Neutrino расширяет семантику POSIX тем, что такое поведение можно заказать выборочно для любого сигнала, в том числе стандартных сигналов Unix. Кроме того, Neutrino позволяет адресовать сигнал к конкретной нити внутри процесса, а не просто к процессу.

Сообщения являются классическим механизмом QNX, который сохранился и в Neutrino, но несколько расширился и усложнился. Помимо синхронных сообщений Neutrino поддерживает короткие асинхронные сообщения, называемые «пульсами» (Pulses) , позволяющие передать 4 байта данных и реализованные на той-же основе, что и сигналы POSIX. Пульсы представляют собой заменитель недостаточно гибкого механизма Proxy, применяемого в QNX.

Введение полноценного понятия нитей потребовало также усложнения механизма передачи сообщений. Если в QNX процессы устанавливали виртуальный канал непосредственно друг с другом, то в Neutrino они должны использовать для этой цели Соединения (connections) и Каналы (channels).


Рис. 9 - Каналы и соединения

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

Системные часы и таймеры

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

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

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

Обработка прерываний

Этот пункт является одним из самых сложных при разработке ОС для системы реального времени, поскольку необходимо выполнить множество плохо согласующихся требований. API обработки прерываний довольно близко соответствует предварительному стандарту POSIX 1003.1d. Модель обработки выглядит следующим образом.

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

К одному прерыванию можно присоединить несколько ISR, при этом они все будут вызваны. ISR должна вернуть управление по-возможности быстро, отложив длительные операции для выполнения соответствующей нитью драйвера и информировав его об этом, например с помощью пульса. Если возвращенное любой из ISR значение указывает на то, что возникло некоторое событие, любого типа, это событие будет буферизовано. После вызова всех ISR микроядро завершает работу с программируемым контроллером прерываний и возвращаяет управление из прерывания. Однако, возврат происходит не обязательно в то место, где оно произошло. Если одно из буферизованных событий вызвало переход более высокоприоритетной нити в состояние READY, то управление будет возвращено в контекст этой этой нити. Основное отличие этой схемы от механизма ISR/DPC, используемого в Windows NT, заключается в том, что все DPC диспетчеризуются с одним и тем-же уровнем приоритета, что означает невозможность вытеснения одного DPC другим и приводит к непредсказуемой задержке обработки более высокоприоритетных прерываний.

Описанная модель обеспечивает очень хорошие временные характеристики (interrupt latency и sheduling latency), поскольку Neutrino запрещает прерывания лишь на очень короткие промежутки времени, не зависящие от данных. Максимальное время задержки обработки прерывания можно вычислить, на основании задержки, вносимой микроядром и суммы времен исполнения всех ISR назначенных для прерываний с более высоким аппаратным приоритетом.


Рис. 10 - Временные характеристики Neutrino при обработке прерываний

Эту сумму также можно контролировать, поскольку Neutrino предоставляет API для переназначения приоритетов уровней прерываний в контроллере. Можно также свести ее к нулю, разработав систему таким образом, чтобы на уровне ISR ничего не делалось, а вся работа происходила бы на уровне нитей с приоритетами, назначенными разработчиком, а не в соответствии с приоритетами аппаратных прерываний.

Наконец, помимо обычных прерываний, нить может перехватить некоторые внутренние события Neutrino, и даже немаскируемые прерывания процессора (NMI). Заметим, что поскольку механизм системных вызовов основан на программных прерываниях, работающих так-же, как и аппаратные, обработка системных вызовов происходит точно так-же, как обработка прерываний. То-есть, вытеснение процессов при обработке прерываний и системных вызовов происходит одинаково быстро.

Практические аспекты применения системы

Как следует из целей проекта Neutrino, эта система должна быть в конечном итоге пригодна для решения таких разных задач, как создание системы управления беспилотным летательным аппаратом, или создание корпоративного Internet-сервера. Замечу, что пригодность системы может быть теоретической или практической, что определяется такими факторами как наличие средств разработки, графических средств, дополнительного программного обеспечения от независимых разработчиков и многих других объективных и субъективных факторов, в том числе общественного мнения.

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

Графическая подсистема Photon

Существует несколько довольно известных операционных систем, пригодных для создания систем реального времени. Однако большинство из них неспособны решить проблему реализации графического интерфейса пользователя (GUI) для встраиваемых систем, поскольку представляют собой очень ограниченные по возможностям realtime executives. Те немногие, что способны поддержать полноценный GUI, например RtLinux, не позволяют извлечь из этого практическую пользу, поскольку реализация традиционных GUI, типа X11, связана с очень высокими затратами ресурсов, особенно памяти.

Начиная проект Neutrino, его разработчики подумали и об этом аспекте. Для реализации GUI, пригодного к использованию во встраиваемых системах реального времени, параллельно был начат еще один проект – Photon. Результатом стало создание графической подсистемы, по внешнему виду и структуре пользовательского интерфейса очень похожей на X11/Motif, но весьма скромной по затратам ресурсов. Такой результат был достигнут благодаря применению при ее разработке принципа модульности и ряда новых фундаментальных идей.

Я уже писал об этой системе достаточно подробно, поэтому не буду повторяться. Интересующиеся могут обратиться к статье «Photon microGUI: По ту сторону картинки», опубликованной в журнале «Мир ПК», No. 11/1996.

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

В настоящее время готовится к выпуску бета-версия Photon 1.12, которая будет содержать ряд новых средств, включая: Версия системы Photon для Neutrino существует в стадии бета-тестирования, но на момент написания статьи еще недоступна для пользователей. 

Резюмируя вышесказанное можно сделать вывод, что изначальная "сырость" системы в значительной степени ликвидирована. C выходом версии 1.12 она сможет успешно конкурировать с системами типа Windows CE и другими, ориентированными на применение в миниатюрных устройствах.

Сетевой сервис и файловая система

Сетевой сервис в Neutrino на данный момент представлен только протоколом TCP/IP. Разработчики Neutrino хотели предоставить пользователям полный набор функциональных возможностей классического стека TCP/IP, но осознавали также потребности рынка встроенных систем, для которых классическая реализация слишком велика и содержит много ненужных элементов. В результате они создали специальную версию стека для встроенных систем – Micro TCP/IP, который занимает всего около 40Kb кода, за счет некоторых ограничений. Для тех же, кому нужны все возможности TCP/IP, например динамическая маршрутизация, будет предоставлен другой вариант, 100% совместимый с BSD-sockets.

Neutrino также будет поддерживать сетевой протокол FLEET, используемый сейчас в QNX, с некоторыми усовершенствованиями, касающимися автоконфигурирования.

Файловая система в Neutrino реализована иначе, чем в QNX. Главное функциональное отличие – ее лучшая приспособленность к сменным носителям. Для этого была изменена модель взаимодействия менеджеров ресурсов и драйверов устройств, примененная в QNX. Если там менеджер файловой системы обращался к драйверу устройства для получения сервиса физического уровня, то в Neutrino все наоборот. Теперь приложение обращается к драйверу, который определяет тип файловой системы (по сигнатурам) и динамически загружает соответствующую файловую систему, реализованную в виде разделяемой библиотеки.

Собственно говоря, файловых систем в Neutrino много. Поддерживаются все файловые системы, имеющиеся в QNX, а также виртуальная файловая система Proc. Для обеспечения обмена данными с другими операционными системами Neutrino также поддерживает файловую систему CIFS (Common Internet File System), которая представляет собой обобщенный вариант SMB, способный использовать любой сервис имен (например DNS) вместо Netbios NS. Разумеется, все файловые системы реализованы с учетом возможности работы в ограниченных ресурсах, то есть очень компактно. Например, код для поддержки файловой системы Tiny QNX (POSIX) занимает всего 12Kb, разумеется за счет некоторых ограничений. Эта система способна читать разделы созданные QNX4, но не может создавать жесткие ссылки и файлы с именами длиннее 16 символов (иначе говоря, не может писать в файл .inodes)

Средства разработки и совместимость

Для успеха любой операционной системы необходимо наличие высококачественных средств разработки приложений. В отличие от большинства систем «типа UNIX», Neutrino имеет свои собственные средства разработки вместо обычного компилятора GCC и связанных с ним программ. Однако, эти средства ничуть не хуже и они вполне стандартны - это компилятор Watcom C/C++ 10.6. Среда разработки включает все стандартные средства Watcom, кроме IDE (пока), которая по неофициальным данным будет доступна после выхода системы Willows под QNX/Photon.

Эта система (Willows) предоставит возможность компиляции приложений написанных с использованием API Win32 под QNX/Neutrino/Photon. При этом обеспечивается поддержка бинарных объектов (DLL от третьих фирм) и непосредственное исполнение приложений Windows (16-битных) через эмуляцию. Однако, перекомпилированные приложения будут иметь преимущество в скорости (вероятно, они будут работать быстрее чем в Windows) и смогут использовать одновременно API системы QNX/Neutrino для выполнения задач реального времени и обмена сообщениями.

Между тем, компилятор GCC 2.7.2 был недавно перенесен в QNX, впоследствии будет перенесен в Neutrino. Ведется работа и над переносом стандартной библиотеки C из Unix (libc). Эти программы бесплатны, что может предоставить неплохое дополнение к системе разработки Watcom. Данный факт может сыграть ключевую роль в ускорении переноса приложений из Unix и включении QNX/Neutrino в список поддерживаемых платформ разработчиками приложений для Unix.

Таким образом, возможно в будущем QNX/Neutrino может стать платформой, на которую можно будет без проблем перенести приложения и из Unix и из Windows! Ведется также разработка системы «кросс-разработки», которая позволит разрабатывать приложения QNX/Neutrino под Windows NT.

Средства работы с Internet и разработка Internet-приложений

Никакая современная ОС не может игнорировать «фактор Internet», поскольку эта среда с каждым днем все более превращается в ту «информационную супермагистраль», о которой все много говорили. В поддержке Internet нет ничего особенно необычного, за исключением того, что и здесь нужно было учесть основное требование встроенных систем – низкие затраты ресурсов. Сочетание QNX/Neutrino и графической системы Photon открывает совершенно новые возможности для рынка встроенных клиентских систем для Internet-устройств «карманного» размера (handheld devices). Фирма QSSL лицензировала WEB-browser фирмы Spyglass (на котором также основан MS Internet Explorer) и разработала комплект клиентских приложений для работы с Internet (Voyager Pro), включающий web-броузер, mail/news-клиент и графическую программу установления соединения с ISP.

Этот комплект доступен почти полностью с исходным кодом, под названием Internet Applliance Toolkit (IAT). Разработчики могут использовать этот код для создания модифицированных версий клиентских программ (browser, mail, news), оптимизированных под конкретные нужды. В результате разработчики получают уникальную возможность создавать встроенные системы с комплектом Internet-приложений за очень короткое время, поскольку все что им потребуется – это модифицировать пользовательский интерфейс с помощью визуального средства разработки (Photon Application Builder).

Для демонстрации возможностей этой технологии на WEB-сервере QSSL http://www.qnx.com/iat появилась новая страничка - QNX Demo Disk. Любой желающий может скачать образ 1.44 дискеты, содержащей демонстрационную версию системы. С этой дискеты нужно загрузиться, жесткий диск не используется, необходимо лишь 6Mb оперативной памяти. После загрузки Вы увидите что эта дискета содержит:

Запустив десяток копий программы анимации (одновременно с остальным), можно увидеть чем отличается хороший дизайн от плохого. Следует заметить, что для создания этой дискеты использована пока система QNX а не Neutrino, что не помешало разработчикам «уместить» все.

Фирма Intel предустанавливает демонстрационную версию системы QNX (лицензия на 30 дней) с графической оболочкой Photon и комплектом Internet Appliance Toolkit на платформу EXPLR2, предназначенную для разработки и отладки встроенных систем. Желающие могут получить бесплатную документацию на платформу (Design Reference Kit, в том числе в электронном виде) от фирмы Intel, обратившись на ее WEB-сервер http://http://www.explr2.com/.

Заключение

Neutrino не является единственной новой разработкой в области операционных систем. Существует несколько других интересных проектов, некоторые из которых построены на принципах сходных с QNX (микроядро и обмен сообщениями) и пригодны для применения в системах реального времени. Такие системы, как L3/L4 и MkLinux имеют также некотороые преимущества перед существующей версией Neutrino, например поддержку алгоритма диспетчеризации EDF и возможность исполнять приложения Linux (которых достаточно много). Тем не менее, ни одна из этих систем не пригодна для применения во встраиваемых системах с ограниченными ресурсами, представляющими наибольший интерес для рынка систем реального времени.

Чем Neutrino отличается от QNX?

Тем кто хорошо знаком с QNX из всего вышесказанного легко понять, что Neutrino имеет множество преимуществ. Не все из них реализованы в версии 1.0, Но ожидается, что следующая версия 1.1 будет поддерживать большую часть объявленных возможностей. Сформулирую вкратце лишь основные достоинства, чтобы легче было ориентироваться в многообразии нововведений: Обратная сторона медали? Перечисленные нововведения настолько глобальны, что они неизбежно должны привести к некоторой несовместимости с QNX 4.x. Однако, разработчики заявляют что будет обеспечена 100% переносимость приложений из QNX в Neutrino. На данный момент это еще не сделано, но в принципе возможно, включая и бинарную совместимость. Кроме того, система еще не полностью закончена, ориентировочный срок выхода полной версии Neutrino - середина 1998 года.

QNX или Neutrino?

Такой вопрос в последнее время возникает как у тех, кто уже давно использует QNX для своих разработок, так и у тех, кто только начинает работу в этой области. QNX4 является на данный момент более полной системой, с точки зрения функциональных возможностей. Она проверена временем, следовательно ее можно считать также более надежной. Однако, ее архитектура отличается меньшей гибкостью, чем у Neutrino, что неизбежно означает некоторое замедление или прекращение ее дельнейшего развития, в пользу Neutrino.

На основании этих соображений, можно сделать несложные выводы. Тем, кто уже разработал свои системы под QNX4 и удовлетворен существующими возможностями, следует пока оставаться с QNX4 и не гнаться за новизной. Тем же, кто только начинает проектировать системы реального времени или ищет новые возможности, имеет смысл ориентироваться на Neutrino. Разработчики ПО общего назначения находятся в более сложной ситуации – им нужно поддерживать старых клиентов, большинство из которых будут еще долго использовать QNX4, в то-же время нужно захватывать позиции на новом рынке.

На данный момент API двух платформ имеют значительные непересекающиеся части, однако представители QSSL утверждают, что эта ситуация будет устранена. Вероятно, тогда проблема станет менее трудной. Уже сейчас в системе Photon, которая будет поддерживаться для обеих платформ, появились функции, маскирующие различия между QNX и Neutrino. Впрочем, это не решит всех проблем. Neutrino предлагает существенно иную парадигму программирования, с сильным акцентом на использование многопоточности, поэтому для ее эффективного использования основной станет проблема переобучения специалистов, привыкших к QNX4. 

Так или иначе, будущее безусловно за Neutrino, но следует заметить, что богатый набор функций, реализованный в соответсвии со стандартами POSIX, уже сейчас делает Neutrino весьма привлекательной альтернативой существующим решениям. Исследования рынка систем реального времени показали, что для систем с жесткими ограничениями ресурсов все еще широко используются различные исполняющие системы (realtime executive) c нестандартизированным API и часто довольно бедными функциональными возможностями. Именно поэтому разработчики Neutrino приняли решение выпустить предварительную версию систему, не имеющую пока возможностей для масштабирования вверх, но уже пригодную для применения во встроенных системах. Не случайно фирма Intel с некоторых пор поддерживает очень хорошие отношения с QSSL и покупает лицензии на Neutrino в огромных количествах. Несмотря на наличие собственной ОС реального времени iRMX, Intel также официально объявила о том, что QNX/Neutrino является для нее «Realtime OS of preference» и отправила около 300 своих инженеров из различных отделений на семинары по изучению QNX/Neutrino.

Тем не менее, «классическая» ветвь QNX4 в какой-то мере пока продолжает развиваться, совершенствуя свои качества. По заявлениям представителей QSSL в дальнейшем будет происходить «миграция» технологий между двумя ветвями (QNX4 и Neutrino), с тем чтобы в конце концов обеспечить плавное и безболезненное слияние, к тому моменту, когда Neutrino будет готова заменить QNX в системах высокого уровня. Неясно пока, сможет ли Neutrino конкурировать с традиционно применяемыми Unix-системами или Windows NT на рынке высокопроизводительных серверов, и станет ли она «Святым Граалем» для широкого круга пользователей, но на рынке встроенных систем реального времени ее ждет несомненный успех.

Всем, кого интересует эта тема я рекомендую посетить WEB-сервер фирмы QSSL http://www.qnx.com/, где можно прочитать также о примерах практического применения системы QNX в самых разнообразных проектах. Информация на русском языке, в том числе эта и другие мои статьи доступна на нашем сервере http://http://www.infomarket.ru/, а также на сервере официального дистрибьютора QNX в России – http://www.swd.ru/.



QNX®, Neutrino и Photon являются торговыми марками фирмы QNX Software Systems Ltd.
Иллюстрации в тексте © QSSL, использованы с ее любезного разрешения.
©1999 by Nigl
Mail to: [email protected]
Last update 99-356
LIST100 Counter SpyLOG In to the Nigl's nest