Особенности национальной автоматизации
Сложность программы растет до тех пор,
пока не превысит способности программиста.
Один из законов Мэрфи
Приходилось ли вам когда-нибудь видеть на экране изображение переворачивающихся песочных часов? Да что вы говорите! Тогда мне будет значительно проще рассказывать о системах реального времени - все познается в сравнении. Только не надейтесь, что сможете сравнивать, превратив в такую систему свой домашний компьютер - назначение этих систем несколько отличается от привычных для него функций. Или в отношении именно вашего компьютера я не совсем прав?
Для начала дадим наиболее употребительное определение вычислительной системы реального времени: это такая система, правильность работы которой определяется не только логической корректностью вычислений, но и временем, требующимся для получения результата вычислений. То есть время получения результата вычислений является критичным параметром, и превышение этого времени эквивалентно логически некорректному функционированию системы.
Разумеется, не всегда имеет смысл говорить о полной эквивалентности логики и времени выполнения: со столь категоричным пониманием приходится сталкиваться не часто. Гораздо чаще понятие реального времени смягчено возможностью немного (или нечасто) опоздать - все как в реальной жизни. Можно опоздать на работу, но нельзя - на обед. Можно опоздать трижды, но на четвертый раз тебя уволят. Зато если неделю приходить вовремя, счетчик попыток обнулится. Практически любой процесс в современных вычислительных системах привязан к событиям: действиям пользователя, аппаратным прерываниям, отсчетам таймера, завершению и изменению состояния других процессов и пр. Реакция системы на отдельные события не допускает промедления вовсе, для других она может быть отложена на некоторое (но не бесконечное) время, с истечением которого событие переходит в категорию не допускающих промедления, для третьих время реакции системы некритично, и достаточно лишь позаботиться о том, чтобы система в принципе не «забыла» обработать событие.
Имеются и соответствующие понятия: «жесткое реальное время» и «мягкое реальное время». Первое предполагает, что все результаты вычислений должны быть получены точно к сроку, и опоздание равносильно неработоспособности системы. Таково большинство систем управления оборудованием типа встраиваемых контроллеров или систем оцифровки звука/изображения. Второе понятие допускает некоторый процент полученных с опозданием результатов, но обязательно ограничивает при этом какой либо другой параметр, например, максимально допустимую частоту, минимальное время между двумя такими случаями опоздания или некую среднестатистическую величину, образованную от указанных, типа средней производительности системы. Здесь, правда, на арену выходит такое понятие, как качество сервиса (Quality of Service, QoS) - величина, верхнее значение которой соответствует работе системы без опозданий, а нижнее - минимально допустимому качеству результата. Пример подобной задачи - воспроизведение цифрового видеопотока: превышение времени обработки в данном случае не фатально и приводит лишь к отдельным нарушениям последовательности воспроизведения в виде выпадения строк или кадров, уменьшая величину QoS. При определенном количестве или частоте выпадений картинка уже не может отображаться правильно, и хотя система не успевает вычислять результат, к примеру, всего лишь в 30% случаев, величина QoS уже равна нулю, так как окончательный результат неудовлетворителен. К этой же категории можно отнести всевозможные интерактивные системы, где время реакции на действия пользователя должно быть если не нормированным, то хотя бы предсказуемым и стабильным: сюда относится, в частности, большинство бытовых устройств и компьютерных систем общего назначения.
Таким образом, понятие реального времени весьма относительно, зависит от выполняемых системой задач и в принципе может быть применимо к любой системе: полагаю, читатели без труда вспомнят, когда им в последний раз приходилось наблюдать за песочными часами на экране. А ведь последствия даже для не связанных с оборудованием систем могут быть и более серьезны: получасовая задержка в системе подтверждения платежеспособности вашей кредитки может не только попортить вам нервы, но и обернуться финансовыми потерями. В определенной степени любая вычислительная система критична ко времени выполнения задач: даже простейший текстовый редактор, отображающий набираемые пользователем символы с задержкой в несколько секунд, вряд ли вызовет положительные эмоции - его величина QoS близка к нулю (а для особо нетерпеливых пользователей и вообще отрицательна).
Разумеется, один из основных факторов, влияющих на работоспособность или QoS системы, - аппаратная вычислительная мощность и объем аппаратных ресурсов. Увеличивая то и другое, можно зачастую существенно уменьшить время реакции системы, но до определенного предела. За этим пределом - выбор иной аппаратной платформы, иной архитектуры построения системы, а то и вовсе применение технологий, не имеющих отношения к программированию. Но это уже тема для другой статьи.
Процесс разработки встраиваемых в оборудование вычислительных систем начинается обычно с выбора «железа», отвечающего поставленным требованиям по функциональности и быстродействию, но здесь я рекомендаций давать не буду. Напомню только, чтобы вы не забыли, что аппаратура без программ - действительно «железо», и рассматривать их надо в комплексе.
Вторым пунктом у нас значится выбор операционной системы. Стоп, в стройном плане разработки никакой ОС не было, только аппаратное и программное обеспечение! Не спешите, все в этом мире относительно.
Простейшие встраиваемые системы зачастую обходятся без всяких ОС и прочих «нахлебников»: приложение, напрямую взаимодействующее с аппаратурой, - не самое плохое решение для такого случая. Приложение пишется по большей части на низкоуровневом языке с использованием в лучшем случае библиотек процедур или макросов либо на адаптированной для конкретной платформы версии высокоуровневого языка (из которого подобная адаптация чаще всего делает уродца с нарушенной структурностью и едва приближающейся к ассемблеру функциональностью). Что из этого получается, читатель, полагаю, знает и без меня. Программа, сотворенная давно ушедшим в более прибыльную область деятельности гением-одиночкой, заставляет продолжателей славного дела автоматизации применять давно снятые с производства комплектующие и трижды морально устаревшую архитектуру, дабы только не разбираться в результатах интеллектуальных извращений автора. Но это все лирика, это от бедности.
Предположим, что финансовый вопрос нас волнует, но не очень. Гораздо больше нас беспокоит то, насколько полно будет отвечать создаваемая система поставленным требованиям. Разумеется, на класс устройств, требующий времени реакции в несколько микросекунд, мы не претендуем - это удел аппаратных решений. Наши требования просты, как лозунги революционеров: долой паразитирующие операционные системы, ресурсы - приложениям, зарплату - программистам (шучу). На самом деле вариант прямого общения приложения с «железом» позволяет держать ситуацию под полным контролем программиста, гарантируя как обеспечение необходимого времени реакции системы (если только мы не промахнулись с выбором аппаратной платформы), так и предсказуемость ее работы, но имеет существенный недостаток: держать под контролем самого программиста весьма трудно. Особенно когда процесс доходит до упомянутой в эпиграфе стадии. Поставленный перед необходимостью усложнения системы и одновременной работы с несколькими процессами, программист обычно находит простое и гениальное решение, которое, если не ошибаюсь, является интернациональным и сотни раз описано в литературе: эстафетная передача управления между процессами по кольцу с обменом данными через общую память. Основные, но не слишком существенные вариации включают передачу управления по таймеру, передачу по изменению состояния процесса или инициированную собственно процессом. Дополнительные - заведение в той же общей памяти всевозможных флагов и семафоров, изменяющих порядок передачи эстафеты. Сохраняя практически все под контролем (хотя и теряя в скорости реакции), разработчики изобретают не что иное, как велосипед, а вернее, отдаленно приближаются к подобию ОС реального времени.
Первейшим назначением любой ОС является обслуживание ресурсов компьютера и их распределение между активными задачами. ОС, претендующая на работу в режиме реального времени, помимо того, должна уметь разбираться с приоритетами задач и передачей им управления в ограниченных временных рамках, сама при этом минимально используя аппаратные ресурсы. Вот тут-то и стоит вспомнить, что вопрос финансовый нас хоть и немного, но все же волнует. Не нужно быть дипломированным экономистом, чтобы оценить стоимость разработки (менее интересно) и последующего сопровождения системы (более интересно). Особенно если учесть необходимость доработок в будущем силами не участвовавших в разработке специалистов. После чего узнать цены на коммерческие программные продукты соответствующего класса и убедиться, что полный комплект лицензий, включая ОС реального времени с API, средствами разработки и отладки, обойдется в несколько тысяч долларов максимально. А сколько вы собираетесь платить команде квалифицированных программистов в месяц?
Если говорить серьезно, то на некотором этапе наращивания сложности системы перед разработчиком встает дилемма: либо пытаться удержать все под своим контролем, обеспечивая механизм многозадачности на уровне приложений или собственных механизмов, либо доверить управление своими задачами ОС стороннего производителя. Таких систем сегодня немало, список займет треть страницы, но основными игроками на рынке систем жесткого реального времени можно назвать OS9, QNX, pSOS+, VxWorks, LynxOS. Впрочем, давать рейтинговые оценки не возьмусь - бездарное это занятие, так как о вкусах не спорят.
Разговор о том, нужно ли вообще применять в некой разработке стороннюю ОС реального времени, подобен обсуждению необходимости применения высокоуровневых языков программирования. И то и другое позволяет значительно сократить время разработки, требуя взамен некоторого увеличения аппаратных ресурсов, но сегодня последнее представляется не столь принципиальным. ОС реального времени в большинстве случаев содержат интерфейсы API, значительно облегчающие работу с ресурсами, и зачастую готовые средства разработки приложений. Так, к примеру, QNX содержит API стандарта POSIX и средства разработки на языке C/C++ - понятия, милые сердцу любого работающего в среде Unix программиста. К тому же все ОС реального времени имеют механизмы, гарантирующие время реакции системы на события, причем это время легко вычислить, исходя из известного времени переключения контекста, блокировки прерываний или выполнения системных вызовов.
Но, как уже догадались читатели, достоинства всегда компенсируются недостатками, и фактор, негативно влияющий на применение готовых ОС, - наличие огромного количества собственного кода, используемого разработчиками начиная от самых первых версий систем, кода, который не всегда тривиально портируется под готовую ОС. К тому же при выборе определенной ОС приходится менять и все остальные средства разработки: трансляторы, отладчики, эмуляторы, и, что самое неприятное, переучивать самих разработчиков. Кроме того, существуют области, где применение имеющихся на рынке коммерческих ОС реального времени может быть не только необоснованно, но и просто недопустимо: это касается, в частности, систем обеспечения безопасности, авиационных и прочих транспортных применений, систем обеспечения жизнедеятельности и медицинских устройств.
Но мы несколько увлеклись, забыв о том, что жесткий подход не всегда оправдан. Для систем мягкого реального времени вполне подойдут и некоторые ОС общего применения, в частности Windows NT/2000, Linux, Windows CE. Придать им особенности, требуемые нашей задачей, помогут специальные расширения реального времени - RTAI, RT Linux, RTX, или, на худой конец, виртуозы-программисты, хорошо разбирающиеся в структуре этих ОС. Во многих случаях эти средства обойдутся дешевле специализированных. Но и тут не удержусь от выливания на вас бочки дегтя. Во-первых, вычислить время выполнения тех же системных вызовов для ОС общего применения если и возможно, то только опытным путем: разработчики не указывают этих параметров. К тому же опытный путь не самый лучший: полученные значения могут соблюдаться при одних условиях и принципиально измениться при других. Правда, для расширений реального времени такие параметры все же приводятся, но, опять же, это цифры, полученные в основном экспериментальным путем, а не жестко заданные структурой системы. Можно, конечно, предусмотреть некоторый запас, но есть ли у вас гарантия, что такового хватит? А отвечать за отказы функционирования системы придется вам, а не разработчику ОС. Во-вторых, существует такое понятие, как стоимость риска. В случае, когда необходимые параметры системы обеспечиваются штатными средствами ОС, этот риск существенно ниже, чем когда применяются дополнительные расширения или нестандартные ухищрения (я бы даже сказал, «извращения»). Представьте себе ситуацию, когда с трудом достигнутый «не совсем штатными средствами» результат вдруг перестанет быть достигнутым в момент установки очередного service pack или новой версии какого-либо компонента. Впрочем, систему можно и не обновлять, но легче от этого не станет: в процессе отладки могут измениться требования к системе, и вы упретесь в непреодолимую преграду в виде пары строк кода, работающего не совсем так, как вы себе представляли. Особенно это касается Linux, для которой найти описание тонкостей работы даже значительно более безобидных функций иногда становится невыполнимой задачей, помочь в решении которой не могут никакие конференции разработчиков.
Не знаю, насколько все вышесказанное поможет вам в работе, но если таковая подвернется и, прежде чем браться за клавиатуру или паяльник, вы вспомните о некоторых из этих мыслей, будем считать, что мы с вами не зря потратили время.
Врезка 1: Ядро и процессы
Врезка 2: Взаимодействие процессов
Врезка 3: Работа с аппаратными прерываниями. Linux в качестве ОС реального времени.
Врезка 4: Windows NT/2000 в качестве ОС реального времени
[i40122]
Ядро и процессы
Одна из принципиальных особенностей ОС реального времени - микроядерная архитектура. Рассмотрим вкратце такую архитектуру на примере QNX. В отличие от ядра операционных систем общего назначения, зачастую выполняющих практически все функции ОС, микроядро QNX (microkernel) выполняет только две задачи: маршрутизацию сообщений между процессами и передачу управления процессам в зависимости от изменения их состояния (результатом которого является генерация сообщения или прерывание). Микроядро планирует передачу управления только внешним процессам и никогда не передает управление самому себе - оно получает его только в виде вызова функции ядра либо через прямое обращение процесса к ядру, либо через аппаратное прерывание.
Типичная конфигурация ОС включает четыре системных процесса. Системные процессы ничем не отличаются от пользовательских приложений - они не имеют ни специальных привилегий, ни каких-либо скрытых от пользователя интерфейсов взаимодействия. Такой подход делает систему «прозрачной» - любая программа может быть установлена как приложение или как системный процесс. К системным процессам относятся и драйверы устройств, которые представляют собой программы, выполняющие рутинную работу по обслуживанию конкретных аппаратных устройств. Установка в систему драйвера заключается всего лишь в запуске соответствующего процесса и никоим образом не затрагивает остальных частей ОС.
Взаимодействие процессов
Рассмотрим (опять же на примере QNX) еще одну принципиальную особенность ОС реального времени - взаимодействие процессов на основе сообщений. Когда в системе выполняются несколько процессов одновременно (надеюсь, не нужно пояснять, что под словом «одновременно» понимается мультизадачность с разделением времени), ОС должна предоставлять механизм для коммуникации процессов друг с другом. В QNX этот механизм - Interprocess Communication (IPC) - основан на передаче сообщений (кстати, QNX была первой коммерческой ОС своего класса, взявшая механизм передачи сообщений в качестве основы взаимодействия процессов). Сообщение представляет собой просто пакет байтов, структура которого не имеет значения ни для кого, кроме отправителя и получателя, включая само ядро.
Но механизм обмена сообщениями не только передает информацию между процессами, но и служит для синхронизации выполнения нескольких процессов. Дело в том, что ядро расценивает факт передачи или приема сообщения как изменение состояния процесса (по сути, генерация сообщения есть результат выполнения некоторой операции). Зная состояние и приоритеты процессов, ядро таким образом может планировать передачу управления между ними, распределяя ресурсы процессора наиболее эффективно.
Работа с аппаратными прерываниями
Не нужно пояснять, что аппаратные прерывания, вызванные внешними событиями, требуют немедленной обработки, однако быстродействие системы не бесконечно, и задержка имеет место в любом случае. Приведем конкретный пример на основе данных для ОС QNX. Несмотря на то, что основную часть времени все аппаратные прерывания в QNX разрешены, некоторые критичные участки кода ядра требуют их запрета. Максимальная длительность таких участков кода (точнее - задержка запуска обработчика прерывания) составляет не более 3,3 мкс для процессора Pentium 166 и не более 22,5 мкс для древнего 386SX 33 (данные для версии 4.24). На практике чаще имеет место случай, когда обработчик прерывания не занимается сам обслуживанием данного прерывания, а лишь активизирует запуск драйвера путем передачи сообщения ядру системы. Суммарная задержка от момента прерывания до передачи управления драйверу составляет для указанных типов процессоров не более 4,7 мкс и 74,2 мкс соответственно. Если же используется механизм прерываний с разными приоритетами, когда высокоприоритетное может прерывать низкоприоритетное, задержка увеличится соответственно числу уровней приоритета, но при этом ее длительность для самого худшего случая можно легко подсчитать, будучи при этом уверенным, что за пределы полученной цифры она не выйдет.
Linux в качестве ОС реального времени
Эта платформа хороша тем, что за нее не нужно платить (если не считать цену носителя и пересылки). Обладая достаточно развитыми средствами разработки приложений общего назначения, система вовсе не имеет средств отладки процессов реального времени. Учитывая большую популярность этой ОС и быстрый рост числа приложений, появление таких средств возможно, но на сегодняшний день рекомендовать Linux в качестве базы для приложений жесткого реального времени нельзя.
Windows NT/2000 в качестве ОС реального времени
Несмотря на то что эта ОС не позиционируется как система реального времени, некоторые зачатки (или наоборот - рудименты?) требуемых механизмов здесь имеются, чего нельзя сказать об ОС класса Windows 95/98/Me. Например, процессы в Windows NT могут относиться к одному из двух классов приоритета: динамическому или реального времени. Большинство пользовательских процессов относится к классу динамических, что означает возможность для ядра системы понижать или повышать их приоритет в соответствии с потребностями и состоянием этих процессов (активен-неактивен). Процессы же класса реального времени всегда имеют более высокий приоритет, чем динамические, но всего лишь семи уровней такого приоритета для практического использования в больших системах явно недостаточно. К тому же ядро системы не рассчитано на встраиваемые применения, так как неработоспособно в бездисковой конфигурации. Для таких случаев имеется модификация Windows NT Embedded.
|