Это компактные системы, основанные на микроядерной архитектуре, - такие так VxWorks, OS-9, PSOS, QNX, LynxOS. Эти системы обладают быстрым временем реакции на события и прерывания, компактностью кода, хорошей встраиваемостью и другими преимуществами, характерными для операционных систем с микроядерной архитектурой.

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

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

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

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

Куда податься?

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

Так как же быть разработчику? Закупать операционную систему реального времени? Или все же есть способ добиться предсказуемого поведения и компактной реализации при использовании традиционных операционных систем?

Смесь бульдога с носорогом

В настоящее время происходит активный процесс слияния универсальных OC и ОС реального времени. На программном рынке появляются различные инструменты поддержки режима реального времени, встраиваемые в привычные операционные системы. Этот класс продуктов обладает значительными преимуществами со стороны пользователей и программистов, сочетая в себе привычный пользовательский интерфейс, средства разработки программ и API-интерфейс реального времени. Правда, пока еще нет оснований утверждать, что подобные решения полностью заменят собой обычные системы реального времени. У традиционных ОС реального времени есть пока большое преимущество - встраиваемость и компактность. Однако и на этом рынке происходят изменения: корпорация Microsoft выпустила Windows NT Embedded (NTE), использование которой позволяет «ужать» NT до 8-10 Мбайт. Уже появились и продукты реального времени, рассчитанные на эту операционную систему, например, RTX.

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

Бурный рост популярности Linux побуждает разработчиков внимательнее присмотреться к этой операционной системе. У Linux много достоинств: открытость кода; большое количество сопутствующего программного обеспечения, пока в основном ориентированного на серверные применения; наличие неплохой документации на API-интерфейс и ядро операционной системы; работа на процессорах различных классов. В данный момент эта ОС готова к стабильной работе, а открытость ее исходных текстов и архитектуры наряду с растущей популярностью заставляет программистов переносить свои наработки на многие аппаратные платформы: SGI, IBM, Intel, Motorola и т.д. В частности, Motorola активно работает в своей традиционной сфере встраиваемых систем и продвигает на рынок продукт LinuxEmbedded. Вообще говоря, Linux прекрасно подходит для компактных встроенных применений; на рынке уже появились поставщики, предлагающие усеченные варианты этой операционной системы, которые занимают 1-2 Мбайт на жестком диске. В качестве примера можно привести проект Linux Router Project.

Для задач реального времени сообщество разработчиков Linux активно применяет специальные расширения - RTLinux, KURT и UTIME, позволяющие получить устойчивую среду реального времени. RTLinux представляет собой систему «жесткого» реального времени, а KURT (KU Real Time Linux) относится к системам «мягкого» реального времени. Linux-расширение UTIME, входящее в состав KURT, позволяет добиться увеличения частоты системных часов, что приводит к более быстрому переключению контекста задач.

KURT

Проект KURT (http://hegel.ittc.ukans.edu/projects/kurt) характеризуется минимальными изменениями ядра Linux и предусматривает два режима работы - нормальный (normal mode) и режим реального времени (real-time mode). Процесс, использующий библиотеку API-интерфейсов KURT, в любые моменты времени может переключаться между этими двумя режимами. Программный пакет KURT оформлен в виде отдельного системного модуля Linux - RTMod, который становится дополнительным планировщиком реального времени. Данный планировщик доступен в нескольких вариантах и может тактироваться от любого системного таймера или от прерываний стандартного параллельного порта. Так как все процессы работают в общем пространстве процессов Linux, программист использует в своих программах стандартные API-интерфейсы Linux и может переключаться из одного режима в другой по событиям, либо в определенных местах программы. При переключении в режим реального времени все процессы в системе «засыпают» до момента освобождения ветви процесса реального времени. Это довольно удобно при реализации задач с большим объемом вычислений, по своей сути требующих механизмов реального времени, например в задачах обработки аудио- и видеоинформации.

Стандартно такты планировщика RTMod задаются от системного таймера - время переключения контекста задач реального времени (time slice) равно 10 мс. Используя же KURT совместно с UTIME, можно довести время переключения контекста задач до 1 мс. Прерывания обрабатываются стандартным для ОС Linux образом - через механизм драйверов.

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

  • set_rtparams позволяет добавить процесс в ядро с маской SCHED_KURT. Только процессы, чья политика в планировщике установлена как SCHED_KURT, смогут работать в режиме реального времени;
  • get_num_rtprocs получает идентификатор «rt_id» процесса из планировщика реального времени RTMod;
  • ? rt_suspend позволяет приостановить планировщик реального времени;
  • get_rt_stats получает статус процесса из таблицы планировщика процессов реального времени.

Простота использования KURT позволяет с максимальным комфортом программировать задачи, требующие как функций реального времени, так и всего многообразия API-интерфейса Unix. Использование «мягкого» реального времени обычно подходит для реализации мультимедийных задач, а также при обработке разного рода потоков информации, где критично время получения результата. Совершенно другой подход применен при реализации в Linux «жесткого» реального времени.

RTLinux

RTLinux (http://luz.cs.nmt.edu/~rtlinux) - это дополнение к ядру Linux, реализующее режим «жесткого» реального времени, которое позволяет управлять различными чувствительными ко времени реакции системы процессами. По сути дела, RTLinux - это операционная система, в которой маленькое ядро реального времени сосуществует со стандартным POSIX-ядром Linux.

Разработчики RTLinux пошли по пути запуска из ядра реального времени Linux-ядра как задачи с наименьшим приоритетом. В RTLinux все прерывания обрабатываются ядром реального времени, а в случае отсутствия обработчика реального времени — передаются Linux-ядру. Фактически Linux-ядро является простаивающей (idle) задачей операционной системы реального времени, запускаемой только в том случае, если никакая задача реального времени не исполняется. При этом на Linux-задачу накладываются определенные ограничения, которые, впрочем, для программиста прозрачны.

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

Все аппаратные прерывания перехватываются ядром операционной системы реального времени. Когда происходит прерывание, ядро RTLinux решает, что делать. Если это прерывание имеет отношение к задаче реального времени, ядро вызывает соответствующий обработчик. В противном случае, либо если обработчик реального времени говорит, что хочет разделять это прерывание с Linux, обработчику присваивается состояние ожидания (pending). Если Linux потребовала разрешить прерывания, то прерывания, которые находятся в состоянии «pending», эмулируются. Ядро RTLinux спроектировано таким образом, что ядру реального времени никогда не приходится ожидать освобождения ресурса, занятого Linux-процессом (рис. 1).

Рис. 1. Механизм работы RTLinux — Linux-расширения жесткого реального времени

Для обмена данными между операционными системами реального времени и Linux могут использоваться следующие механизмы:

  • разделяемые области памяти;
  • псевдоустройства, предоставляющие возможность обмена данными с приложениями реального времени.

Ключевой принцип построения RTLinux - как можно больше использовать Linux и как можно меньше собственно RTLinux. Действительно, именно Linux заботится об инициализации системы и устройств, а также о динамическом выделении ресурсов. «На плечи» RTLinux ложится только планирование задач реального времени и обработка прерываний. Для простоты запуска в контексте ядра, сохранения модульности и расширяемости системы процессы реального времени реализованы в виде загружаемых модулей Linux. Как правило, приложение реального времени с RTLinux состоит из двух независимых частей: процесса, исполняемого ядром RTLinux, и обыкновенного Linux-приложения.

Для иллюстрации работы приложения реального времени рассмотрим прикладной модуль, который использует ядро реального времени RTLinux в виде загружаемого модуля Linux:

#define MODULE
#include 
/* необходимо для задач 
реального времени */
#include 
#inlcude 
RT_TASK mytask;

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

Рис. 2. Механизм межпроцессной связи через очереди сообщений FIFO

Модуль реального времени читает данные из устройства и кладет их в очередь сообщений, откуда их потом забирает обыкновенное приложение Linux.

Как и каждый модуль Linux-ядра, процесс реального времени должен выполнить процедуры инициализации и завершения аналогичные модулям Linux:

int init_module(void)
{
/* определить номер 
очереди сообщений */
	#define RTFIFODESC 1
/* взять локальное время */
RTIME now = rt_get_time()
rt_task_init(&mytask, mainloop, 
RTFIFODESC,3000, 4);
rt_task_make_periodic(&mytask, 
now+1000, 25000);
return 0;
}

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

На наш взгляд, оба подхода в реализации механизмов реального времени, заложенные в KURT и RTLinux, применимы для большинства задач реального времени. Правда, до определенного времени проект KURT находился в «подвешенном» состоянии и почти год не развивался, что вывело команду RTLinux в лидеры этого технологического направления. Однако совсем недавно вышла новая версия KURT 2.0 для Linux-ядер версий 2.2.5, 2.2.9 и 2.2.13.

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

Об авторe

Алексей Черемисин и Олег Кобызевменеджеры компании «РТСофт». С ними можно связаться по электронной почте по адресам

cheremisin@rtsoft.msk.ru и kom@lvl.ru соответственно.