Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


Обработка прерываний и исключений




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

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

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

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

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

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

Реакция на исключения (exceptions)1 похожа на обработку прерываний. Исклю­чениями называются нештатные ситуации, когда процессор не может правильно вы­полнить команду. Примером исключения является деление на ноль или обращение по несуществующему адресу. В англоязычной литературе для разных видов исклю­чений применяются термины trap, fault, abort.

Обычно операционная система обрабатывает исключения, прекращая текущий процесс, и выводит сообщение, четко описывающее ситуацию, на устройство отобра­жения, обычно монитор или принтер. Приемлемая при интерактивной многопользова­тельской последовательной обработке, внезапная остановка процесса в системах ре­ального времени должна быть абсолютно исключена. Нельзя допустить, чтобы Управляемые микропроцессором автопилот самолета или автоматическая тормозная система автомобиля (Automatic Braking System — ABS) внезапно прекратили работу из-за Деления на ноль. В системах реального времени все возможные исключения должны анаализироваться заранее с определением соответствующих процедур обработки.

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

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


Не путать с "взаимным исключением" — mutual exclusion

 

10.6.5. Программирование операций ожидания

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

wait (п)

и

wait until (время)

где п — интервал в секундах или миллисекундах, а переменная "время" имеет формат часы, минуты, секунды, миллисекунды

Когда выполняется одна из этих функций, операционная система помещает про­цесс в очередь ожидания. После истечения/наступления заданного времени процесс переводится в очередь готовых процессов.

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

repeat (* холостой ход *) until (time = 12:00:00);

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

Важной особенностью процессов, запускаемых периодически, — например, филь­трация и алгоритмы регулирования, — является накопленная ошибка времени. Это связано с тем, что процесс из очереди ожидания события опять попадает в очередь, но уже готовых процессов и должен ждать некоторый случайный интервал времени прежде, чем получит управление (рис. 10.9 а). Требуемое и фактическое время про­буждения процесса не совпадают. Ошибки ожидания накапливаются, если это время рассчитывается так

новое время пробуждения = время начала ожидания + интервал

По такому алгоритму работает холостой цикл "ждать 10 секунд". Накопленная временная ошибка представляет собой сумму времени, проведенного в очереди, и времени, необходимого для непосредственного исполнения. Правильное решение получается, если отсчет ведется от момента предыдущего пробуждения

новое время пробуждения = время предыдущего пробуждения + интервал

Таким образом, относительное время преобразуется в абсолютное. На практике не­обходимы две команды

wait until (ref_time);

ref time := ref time +10 seconds;

 

 


10.6.6. Внутренние подпрограммы операционной системы

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

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

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

 

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

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

 

10.6.7. Приоритеты процессов и производительность системы

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

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

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

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

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

 

В развитых и сложных операционных системах, таких как UNIX и Windows NT, и в еще большей степени в распределенных операционных системах, доступ к большин­ству функций (ввод/вывод, сетевая поддержка и т. д.) происходит через системные вы­зовы или механизм удаленного вызова процедур (раздел 10.5.4). В прикладных програм­мах для вызова системных функций используется довольно простая нотация, за которой, как правило, стоит длинная последовательность действий операционной системы. Если между двумя процессами, исполняющимися в разных узлах сети, организован про­граммный канал, то считывание одного символа из этого канала требует целой серии операций в обоих узлах. Поскольку на эти операции обычно наложены жесткие ограни­чения по времени, необходимо провести глубокий предварительный анализ прежде, чем принимать то или иное проектное решение. Если локальная сеть используется не только задачами реального времени, но и интерактивными пользователями, то от количества и активности последних в значительной мере зависит и ее общая нагрузка.

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

 

10.6.8. Тестирование и отладка

Доказательство правильности работы программы является обязательным шагом в ее разработке. Необходимо проверить, что программа выполняет свои функции без ошибок. Визуальные и формальные методы позволяют выявить только ограниченное количество ошибок. На практике это означает, что формальная теория тестирования имеет мало смысла, а основную роль играет собственный опыт и "народные програм­мистские" предания. Реальное тестирование проводится в "боевых" условиях.

Выявлять ошибки трудно — многие из них проявляются спорадически и их нельзя воспроизвести по желанию. Никакое доказательство не может гарантировать, что программа полностью свободна от ошибок, и никакие тесты не могут убедить, что выявлены все ошибки. Цель тестирования — найти как можно большее число ошибок, гарантировать, что программа работает с разумной надежностью. Один из создателей теории операционных систем, Эдсгер Дейкстра (Edsger Dijkstra), заметил: "Тесрование может доказать только наличие ошибок, но не их отсутствие". Тщательный тест требует соответствующей разработки и подготовки; необходимое сочетание практических и аналитических тестов. Сначала тестовые процедуры и данные и ожидаемые результаты описываются в специальном документе. В процессе тестирования ведется журнал испытаний, который затем сравнивается со спецификацией тестов. Желательно, чтобы коллектив разработчиков системы отличался от того, который будет определять процедуры испытаний и проводить их.

При тестировании систем реального времени существует дополнительная сложность из-за большого количества возможных взаимосвязей между задачами. Вероят­ность новой ошибки при исправлении старой очень велика — имеющий опыт разработки программ размером свыше 10 000 строк дает вероятность в пределах от 15 до 50%.

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

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

В многозадачных системах программные модули вначале тестируются отдельно Во время такого тестирования должно быть проверено, что каждая строка програм­мы выполняется хотя бы один раз. Иными словами, если программа содержит коман­ды ветвления типа "if..then..else", то тестовые данные должны обеспечить выполне­ние обеих ветвей.

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

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

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

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

 

 

10.7. Языки программирования и операционные системы реального времени

10.7.1. Требования к языкам и операционным системам реального времени

Программирование в реальном времени требует специальных средств, которые не всегда встречаются в обычных языках последовательного программирования. Язык или операционная система для программирования в реальном времени должны пре­доставлять следующие возможности:

- описание параллельных процессов;

- переключение процессов на основе динамических приоритетов, которые могут изменяться, в том числе и прикладными процессами;

- синхронизация процессов;

- обмен данными между процессами;

- функции, связанные с часами и таймером, абсолютное и относительное время ожидания;

- прямой доступ к внешним аппаратным портам;

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

- обработка исключений.

Немногие языки обеспечивают все эти возможности. Большинство имеет лишь часть из них, хотя для определенных приложений этого оказывается достаточно. Неко­торые компании разработали специальные языки для поддержки своих собственных аппаратных средств. Эти языки не претендуют на универсальность и ориентированы скорее на конкретные ЭВМ и их интерфейсы. Обычно они базируются на существую­щих языках — FORTRAN, BASIC — с расширениями, включающими функции реаль­ного времени, о чем свидетельствуют их названия типа "Process BASIC" и "Real-time FORTRAN". Некоторые языки не поддерживают программирования в реальном вре­мени в строгом смысле, но они легко расширяются, например С и С++.

В 1970-е годы широкую поддержку получила концепция единого переносимого мно­гоцелевого языка программирования. В результате был разработан язык ADA. Его глав­ная идея состоит в том, что среда программирования, т. е. язык, должна быть полностью отделена от аппаратных средств. Программист не должен сталкиваться с деталями машинного уровня, а работать только в терминах абстрактных структур и типов данных.

Опыт показал нереалистичность такого подхода. Универсальные, сильно типизи­рованные языки программирования гарантируют определенный уровень надежности программы, но в то же время ограничивают гибкость. Быстрое развитие технических средств предъявляет новые требования, которые не могли быть предусмотрены в сущеествующих языках, и многие программисты чувствуют ограничения, используя не самые современные языки программирования. Цена надежности языка — слож­ность и громоздкость, а генерируемый при этом компилятором код — избыточен и малоффективен. Открытый язык типа С, основаный на ограниченном количестве базовых идей, обладает большей гибкостью и предоставляет опытному программисту больше возможностей. Не существует наилучшего языка - для каждого приложе­ния и среды необходимо подбирать свои средства и при этом учитывать квалификацию и предпочтения разработчиков.

 


Поделиться:

Дата добавления: 2015-04-05; просмотров: 234; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.006 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты