Игорь Обухов
Тестовая лаборатория
Что общего между кухонным комбайном, станком с ЧПУ, атомной электростанцией и спутником связи? Кроме того, что во всех этих устройствах присутствует электроника, еще и то, что эта электроника работает под управлением одной операционной системы - QNX.
Эта ОС, обладающая уникальной масштабируемостью, была недавно установлена на тестовой системе у нас в редакции. Результаты общения с ней легли в основу этой статьи.
Для начала несколько слов о том, что же такое QNX. Это UNIX-подобная ОС реального времени, основанная на микроядре. Микроядро является, пожалуй, одной из самых интересных частей QNX. Оно отличается интересной архитектурой, неплохими показателями быстродействия, предоставлением интересных сервисов приложениям; кроме того, оно ответственно и за возможность работы в реальном времени. В QNX реализованы все системные вызовы, необходимые по стандарту POSIX.
Микроядро имеет объем менее 32 Кб, т. е. это одно из самых маленьких ядер среди всех существующих операционных систем. В этом объеме помещаются:
- блок передачи сообщений (IPC - межпроцессное общение);
- редиректор прерываний;
- блок планирования выполнения задач;
- сетевой интерфейс.
Все сервисы QNX, не реализованные непосредственно в ядре, работают как стандартные процессы. В типичной конфигурации присутствуют следующие системные процессы:
- менеджер процессов (Proc);
- менеджер файловой системы (Fsys);
- менеджер устройств (Dev);
- менеджер сети.
С точки зрения операционной системы, системные процессы ничем не отличаются от всех остальных. Как, впрочем, и драйверы устройств. Единственное, что нужно сделать, написав новый драйвер устройства в QNX, чтобы он стал частью операционной системы, - это изменить конфигурационный файл системы так, чтобы драйвер запускался при загрузке.
Блок передачи сообщений занимается пересылкой сообщений между процессами и является одной из важнейших частей операционной системы, так как все общение между процессами, в том числе и системными, происходит через сообщения. Система QNX, часто применяемая во встраиваемых системах, имеющих ограниченные ресурсы, использует несколько хитростей для уменьшения нагрузки на процессор и уменьшения количества используемой памяти. Рассмотрим, как происходит общение “процесса А” и “процесса Б”. Обычно сеанс передачи сообщения от “процесса А” “процессу Б” состоит из следующих шагов: “процесс А” выполняет процедуру Send() и посылает сообщение “процессу Б”, в этот момент “процесс А” блокируется на передачу и не может посылать сообщений. “Процесс Б” в какой-то момент выполняет функцию Receive() и принимает посланное ему сообщение. Начиная с этого момента “процесс Б” становится заблокированным на прием и не может принимать сообщения. “Процесс Б” обрабатывает полученное сообщение и выполняет процедуру Reply(), посылая ответ “процессу А”, после чего “процесс Б” снова может принимать сообщения, но не может посылать ответы, пока “процесс А” не получит направленный ему ответ. “Процесс А” получает ответ и после этого снова может посылать сообщения, а “процесс Б” посылать ответы. При этом посылаемые сообщения и ответы находятся в теле отправляющего их процесса до того момента, когда они могут быть приняты. Это значит, что, с одной стороны, уменьшается вероятность повреждения сообщения в процессе передачи, а с другой - уменьшается объем оперативной памяти, необходимый для работы ядра. Кроме того, уменьшается число пересылок из памяти в память, что разгружает процессор. Особенностью процесса передачи сообщений является то, что в сети, состоящей из нескольких компьютеров под управлением QNX, сообщения могут прозрачно передаваться процессам, выполняющимся на любом из узлов.
Определены в QNX еще и два дополнительных метода передачи сообщений - метод представителей (Proxy) и метод сигналов (Signal). Представители используются в случаях, когда процесс должен передать сообщение, но не должен при этом блокироваться на передачу. В таком случае вызывается функция qnx_proxy_attach() и создается представитель. Он накапливает в себе сообщения, которые должны быть доставлены другим процессам. Любой процесс, знающий идентификатор представителя, может вызвать функцию Trigger(), после чего будет доставлено первое в очереди сообщение. Функция Trigger() может вызываться несколько раз, и каждый раз представитель будет доставлять следующее сообщение. При этом представитель содержит буфер, в котором может храниться до 65 535 сообщений.
Сигналы уже давно используются в ОС Unix. QNX поддерживает множество сигналов, совместимых с POSIX, большое количество сигналов, традиционно использовавшихся в Unix (поддержка этих сигналов реализована для совместимости с переносимыми приложениями, и ни один из системных процессов QNX их не генерирует), а также несколько сигналов, специфичных для QNX. По умолчанию любой сигнал, полученный процессом, приводит к завершению процесса (кроме нескольких сигналов, которые по умолчанию игнорируются). Но процесс с приоритетом уровня “superuser” может защититься от нежелательных сигналов. В любом случае процесс может содержать обработчик для каждого возможного сигнала. Сигналы удобно рассматривать как разновидность программных прерываний.
Редиректор прерываний является частью ядра и занимается перенаправлением аппаратных прерываний в связанные с ними процессы. Благодаря такому подходу возникает один побочный эффект - с аппаратной частью компьютера работает ядро, оно перенаправляет прерывания процессам - обработчикам прерываний, для чего используется Far Jump, а это означает, что для написания обработчика прерываний можно использовать Cи, а не Ассемблер. Обработчики прерываний обычно встроены в процессы, хотя каждый из них исполняется асинхронно с процессом, в который он встроен. Обработчик исполняется в контексте процесса и имеет доступ ко всем глобальным переменным процесса. При работе обработчика прерываний прерывания разрешены, но обработчик приостанавливается только в том случае, если произошло более высокоприоритетное прерывание. Если это позволяется аппаратной частью, к одному прерыванию может быть подключено несколько обработчиков, и каждый из них получит управление при возникновении прерывания.
Блок планирования выполнения процессов занимается обеспечением многозадачности. В этой части ОС предоставляет разработчику огромный простор для выбора той методики выделения ресурсов процессора задаче, которая обеспечит наиболее подходящие условия для критических приложений, или обеспечит такие условия для некритических приложений, что они выполнятся за разумное время, не мешая работе критических приложений. QNX дает возможность установить для приложения три варианта обслуживания. Первый наиболее близок к кооперативной многозадачности. То есть процесс выполняется до тех пор, пока он не перейдет в состояние ожидания сообщения, состояние ожидания ответа на сообщение или не отдаст управление ядру. При переходе в одно из таких состояний процесс помещается последним в очередь процессов с таким же уровнем приоритета, а управление передается процессу с наибольшим приоритетом. Во втором варианте все происходит так же, как и в предыдущем, с той разницей, что период, в течение которого процесс может работать без перерыва, ограничивается неким квантом времени. Третий вариант называется адаптивной многозадачностью. В этом случае по истечении кванта времени, выделенного процессу, его уровень приоритета снижается на единицу. Если на новом уровне приоритета процессов нет, то процесс продолжает выполняться, а после окончания этого кванта времени его приоритет снова снижается. Если управление к процессу, работающему в режиме адаптивной многозадачности, не попадает в течение некоторого времени, то его приоритет повышается на единицу, до тех пор пока он не начнет выполняться или пока уровень приоритета не достигнет начального. По умолчанию процессы запускаются в режиме адаптивной многозадачности. В этом же режиме работают все системные утилиты QNX. Очень интересно то, что процессы, работающие в разных режимах многозадачности, могут одновременно находиться в памяти и исполняться.
Приоритет процесса - важный элемент многозадачности. Обычно приоритет процесса устанавливается при его запуске. Но есть дополнительная возможность, называемая “Вызываемый клиентом приоритет”. Обычно она реализуется для серверных процессов (исполняющих запросы на какое-либо обслуживание). При этом приоритет процесса-сервера устанавливается только на время обработки запроса и становится равным приоритету процесса-клиента.
Сетевой интерфейс в системе QNX является неотъемлемой частью ядра. Он, конечно, взаимодействует с сетевым адаптером через сетевой драйвер, но базовые сетевые сервисы реализованы на уровне ядра. При этом передача сообщения процессу, находящемуся на другом компьютере, ничем не отличается с точки зрения приложения от передачи сообщения процессу, выполняющемуся на том же компьютере. Благодаря такой организации сеть превращается в однородную вычислительную среду, наконец-то оправдывая русскоязычный вариант названия - “Локальная вычислительная сеть”. При этом для большинства приложений не имеет значения, с какого компьютера они были запущены, на каком исполняются и куда поступают результаты их работы. В наших тестах удалось создать ситуацию на двух компьютерах, когда задача была запущена с (условно назовем) “компьютера А” на “компьютере Б”, при этом весь вывод на экран задача осуществляла на экран “компьютера А”, а на “компьютере Б” была запущена программа, показывавшая содержимое экрана “компьютера А”. Код для обеспечения сетевого взаимодействия в приложении становится ненужным, скорее потребуется специальный код для определения, работает приложение на одном компьютере или на нескольких, и если на одном, то на каком именно.
Несколько слов о файловой системе. QNX - ОС реального времени, и одним из критических и медленных ресурсов является жесткий диск. Поэтому необходимо использовать надежную высокоэффективную файловую систему и эффективно работать с ней. В QNX реализована файловая система, основанная на экстентах (extent). Для обеспечения высокой скорости работы с диском запросы на запись сортируются, и запись производится за один проход блока головок по диску. Кроме того, применяется буферизация (кэширование), есть специальный режим для временных файлов, к которым происходит частое обращение, - эти файлы хранятся в буфере в памяти и записываются на диск только в случае острой необходимости. Но вся важная системная информация, такая, как блоки расширения и файлы карты занятых блоков, записывается в обход буфера и вне очереди. В менеджер файловой системы встроена возможность создания в ОЗУ “диска”, работа с которым реализована через стандартные средства передачи сообщений, что еще более повышает его эффективность.
Нас приятно поразили минимальные требования к аппаратному обеспечению - для нормальной работы QNX требуется компьютер с процессором 386 или выше и 1 Мб оперативной памяти. При использовании QNX на файл-сервере рекомендуется использовать 4 Мб ОЗУ. Существует версия ядра под названием Neutrino, которой для исполнения достаточно всего 64 Кб памяти. Очень нехарактерен для нашего времени объем, занимаемый этой системой на жестком диске, - вся система с графической оболочкой умещается в 15 Мб, а комплект, состоящий из системы разработки (Watcom C++) и комплекта для разработки приложений, запускаемых из графической системы Photon, заняли еще около 100 Мб. Кстати, графическая оболочка Photon на компьютере с процессором 486DX-2/66 загружается менее 10 с.
Очень интересны возможности по обеспечению высокой надежности функционирования сети. В каждый компьютер можно установить несколько сетевых адаптеров (два, три и даже больше) и проложить между компьютерами несколько сетевых кабелей. В такой конфигурации автоматически определяются проблемы с сетевой проводкой и происходит переключение на адаптер, который подсоединен к исправному кабелю. Кроме того, если в одном компьютере установлено два сетевых адаптера, соединенных с разными сетями, то автоматически происходит маршрутизация пакетов из одной сети в другую.
К недостаткам системы можно отнести сложность ее настройки, особенно в достаточно большой сети, очень узкий круг поддерживаемого аппаратного обеспечения. Однако обеспечить с должным качеством поддержку всех существующих компьютеров во всех возможных конфигурациях - задача сродни объятию необъятного, т. е. с должным качеством невыполнимая. Так что те небольшие недостатки, которые есть в этой системе, являются продолжением ее достоинств. Кроме того, эта ОС все же в первую очередь рассчитана на поддержку критичных приложений (например, управления ядерным реактором), а вот как ОС для файл-сервера она пригодна (и очень хороша с технической точки зрения), но неудобна.
В заключение хочется выразить благодарность фирме SWD Real Time Systems, единственному российскому дистрибьютору фирмы QNX, предоставившему нам операционную систему, инструменты разработчика, а также сделавшую прекрасный русификатор для операционной системы QNX.
Адрес фирмы QNX Software Systems: www.qnx.com.