Главная страница Цифровые системы [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [72] [ 73 ] [74] [75] [76] [77] [78] [79] [80] [81] [82] [83] [84] [85] [86] [87] [88] [89] [90] Так как в многозадачной среде системные программы и примитивы могут вызь, ваться одновременно разными процессами, их код всегда реентерабелен, Это погво ляет избежать конфликтов при прерывании системной программы другим запросом требующим ту же услугу из другого контекста. В некоторых случаях для доступа к внутренним ресурсам операционной системы можно использовать библиотечные модули. Эти модули уже предварительно отко--. пилированы, и их остается только связать с основной программой. Необходимо проверить по документации системы требуемые параметры, а также механизмы их передачи и редактирования связей в языке высокого уровня. 10.6.7. Приоритеты процессов и производительность системы Многозадачная операционная система реального времени должна допускать назначение приоритетов исполняемым процессам. Обычно приоритеты являются динамическими, что означает, что во время исполнения они могут изменяться как самими процессами, так и операционной системой. Обычно существуют определенные ограничения и механизмы контроля, которые определяют, кто и как может менять приоритеты. Назначение приоритетов оказывает серьезное влияние на работу системы в целом. Наиболее важные процессы или процессы, время реакции которых жестко ограничено, получают более высокий приоритет. К последним относятся обработчики прерываний. Задачи, выполняющие менее важные действия, например печать, получают более низкий приоритет. Очевидно, что необходимо обращать внимание на соглашения, используемые в системе относительно того, связан ли более высокий приоритет с большим или меньшим числом. Приоритеты имеют относительное значение и оказывают влияние только тогда, когда существуют процессы с разными приоритетами. В системах реального времени реакция на прерывания отделена от вычислении, требующих значительных ресурсов процессора. Как только происходит событие или прерывание, его обработчик немедленно включается в очередь готовых процессов. Программы обработчиков прерываний обычно компактны, так как они должны обеспечивать быструю реакцию, например ввод новых данных, и передавать управление более сложным процессам, интенсивно потребляющим ресурсы процессора, которые исполняются с более низким приоритетом. В вышеприведенном примере системы управления манипулятором робота (р дел 10.6.3) одна задача, которую можно построить как обработчик прерывании, ЖД поступления от датчика новых данных о текущем положении манипулятора, о поступает прерывание от датчика - есть новые данные, - эта задача должна ср получить управ./1ение. Затем она передает данные о положении программе ° ботки, требующей больших вычислительных ресурсов. Эта программа ие отвеч обработку прерываний и может использовать больше времени для вычислении. Производительность системы реального времени значительно тРУД" "°5,ч-оценке, чем систем, использующих обычные последовательные программы. Вели „ ная последовательная программа исполняется на конкретном процессоре с , скоростью, то программа реального времени зависит от поведения окружающей Р т. е. управляемых технических процессов. Общая производительность системы ДО „ быть достаточной для того, чтобы выполнять все операции и выдавать результаты тановленное время. Иными словами, система реалыюго времени всегда должна Ььп това к максимальной нагрузке, которую может создать технический процесс. В развитых и сложных операционных системах, таких как UNIX и Windows NT, J, в еще большей степени в распределенных операционных системах, доступ к большинству функций (ввод/вывод, сетевая поддержка и т. д.) происходит через системные вызовы или механизм удаленного вызова процедур (раздел 10.5.4). В прикладных программах для вызова системных функций используется довольно простая нотация, за которой, jaic правило, стоит длинная последовательность действий операционной системы. Если между двумя процессами, исполняющимися в разных узлах сети, организован программный канал, то считывание одного символа из этого канала требует целой серий-операций в обоих узлах. Поскольку на эти операции обычно наложены жесткие ограничения по времени, необходимо провести глубокий предварительный анализ прежде, чем принимать то или иное проектное решение. Если локальная сеть используется не только задачами реального времени, но и интерактивными пользователями, то от количества и активности последних в значительной мере зависит и ее общая нагрузка. Многозадачные операционные системы имеют команды, показывающие в каждый момент все активные процессы, их текущий статус (например, ожидание ввода/ вывода, ожидание прерывания и т. д.) и долю в потреблении ресурсов процессора с момента последней перезагрузки системы или какого-либо иного события. Первый шаг по проверке характеристик системы - анализ ее работы с помощью подобной команды. Выявление процессов, занимающих слишком большую долю процессорного времени, может быть хорошей отправной точкой для поиска узких мест и оптимизации характеристик системы. Нет ничего плохого в том, если некоторые процессы загружают процессор больше, чем другие, однако разработчик системы должен иметь ясное представление о том, когда это происходит и почему. 10.6.8. Тестирование и отладка Доказательство правильности работы программы является обязательным шагом нее разработке. Необходимо проверить, что программа выполняет свои функции без ошибок. Визуальные и формальные методы позволяют выявить только ограниченное Количество ошибок. На практике это означает, что формальная теория тестирования имеет мало смысла, а основную роль играет собственный опыт и "народные програм-•истские" предания. Реальное тестирование проводится в "боевых" условиях. ыявлять ошибки трудно - многие из них проявляются спорадически и их льзя воспроизвести по желанию. Никакое доказательство не может гарантировать, вь1яв° полностью свободна от ошибок, и никакие тесты не могут убедить, что и Га ошибки. Цель тестирования - найти как можно большее число ошибок ej нтировать, что программа работает с разумной надежностью. Один из создате-тиров"" """""" систем, Эдсгер Дейкстра (Edsger Dijkstra), заметил: "Тес- ТщэтТ доказать только наличие ошибок, но не их отсутствие". 0 соч" требует соответствующе!! разработки и подготовки; необходи-*анные практических и аналитических тестов. Сначала тестовые процедуры и етип °г1Даемые результаты описываются в специальном документе. В процессе ацией"" ведется журнал испытаний, который затем сравнивается со специфи-Того Желательно, чтобы коллектив разработчиков системы отличался от который будет определять процедуры испытаний и проводить их. ФИ тестировании систем реального времени существует дополните . -------------» -- существует дополнительная слож- из-за большого количества возможных взаимосвязей между задачами. Вероят- ность внесения новой ошибки при исправлении старой очень велика - имеющий опыт разработки программ размером свыше 10 ООО строк дает вероятность в преде лах от 15 до 50%. Существует два основных метода тестирования - исчерпывающий и на приме pax. При исчерпывающем тестировании проверяются все возможные комбинации входных и выходных данных. Очевидно, что этот метод можно использовать лишь в случае, если число таких сочетаний невелико. Метод испытаний на примерах используется наиболее часто. Производится выбор репрезентативного числа сочетаний входа и выхода. Тестовые данные должны также включать крайние значения, например находящиеся за пределами допустимого диапазона. Тестируемый модуль должен правильно распознать и обработать эти данные. В многозадачных системах программные модули вначале тестируются отдельно. Во время такого тестирования должно быть проверено, что каждая строка программы выполняется хотя бы один раз. Иными словами, если программа содержит команды ветвления типа "if..then..else", то тестовые данные должны обеспечить выполнение обеих ветвей. На этой фазе тестирования обычно полезны отладчики. Они позволяют непосредственно просматривать и изменять регистры процессора и области памяти при исполнении машинного кода. Отладчик вставляет в машинный код программы точки останова, в которых можно проверить состояние регистров и переменных и сравнить их со значениями, требуемыми логикой процесса. Однако с ростом сложности операционных систем и расширением функциональности системных вызовов, код которых обычно неизвестен программисту, использование отладчика может оказаться мало полезным. Обычные пошаговые отладчики не позволяют полностью оценить взаимодействие между несколькими параллельными процессами. Однако отладчики являются полезными и необходимыми средствами при разработке программ на ассемблере. Только после того как все модули были проверены по отдельности и все обнаруженные ошибки исправлены, можно приступать к параллельному исполнению для отладки взаимодействия. Многочисленные взаимосвязи программных модулей могут привести к ошибкам в системе, даже если отдельные модули работают правильно. Общая работа системы - время обработки прерываний, производительность при разной нагрузке - проверяется на основе тестовой спецификации. Особое внимание следует обратить на функции, обеспечивающие надежность и безопасность системы. Если система включает в себя обработку прерываний и исключений, то необходи мо проверить корректность соответствующей реакции. Имитация ошибочных ситуа ций позволяет оценить их последствия для системы и ее поведение в этом случае. Результаты тестов отдельных модулей и комплексной отладки заносятся в протокол испытаний, и на его основе вносятся необходимые исправления. Не следует забывать, что ошибки тем труднее исправляются, чем позже они были обнаружены-Расходы на тестирование - это инвестиции не только в качество системы, но и в ее общую экономическую эффективность, поскольку значительная часть расходов в течение жизненного цикла системы уходит на ее сопровождение, т. е. в конечном счете на выявление и устранение ошибок. Дальнейшее обсуждение надежности программного обеспечения приведено в разделе 12.3.4. 0.7. Языки программирования и операционные системы реального времени 10-7.1 Требования к языкам и операционным системам реального времени Программирование в реальном времени требует специальных средств, которые не всегда встречаются в обычных языках последовательного программирования. Язык лли операционная система для программирования в реальном времени должны предоставлять следующие возможности: - описание параллельных процессов; - переключение процессов на основе динамических приоритетов, которые могут изменяться, в том числе и прикладными процессами; - синхронизация процессов; - обмен данными между процессами; - функции, связанные с часами и таймером, абсолютное и относительное время ожидания; - прямой доступ к внешним аппаратным портам; - обработка прерываний; - обработка исключений. Немногие языки обеспечивают все эти возможности. Большинство имеет лишь часть из них, хотя для определенных приложений этого оказывается достаточно. Некоторые компании разработали специальные языки для поддержки своих собственных аппаратных средств. Эти языки не претендуют на универсальность и ориентированы скорее на конкретные ЭВМ и их интерфейсы. Обычно они базируются на существующих языках - FORTRAN, BASIC - с расширениями, включающими функции реального времени, о чем свидетельствуют их названия типа "Process BASIC" и "Real-time FORTRAN". Некоторые языки не поддерживают программирования в реальном времени в строгом смысле, но они легко расширяются, например Си C-I--I-. В 1970-е годы широкую поддержку получила концепция единого переносимого многоцелевого языка профаммирования. В результате был разработан язык ADA. Его главная идея состоит в том, что среда профаммирования, т. е. язык, должна быть полностью Отделена от аппаратных средств. Программист не должен сталкиваться с деталями ма-"iHHHoro уровня, а работать только в терминах абстрактных структур и типов данных. Опыт показал нереалистичность такого подхода. Универсальные, сильно типизи-ванные языки программирования гарантируют определенный уровень надежнос-программы, но в то же время ограничивают гибкость. Быстрое развитие техничес-И- средств предъявляет новые требования, которые не могли быть предусмотрены в УЩествующих языках, и многие программисты чувствуют ограничения, используя. самые современные языки программирования. Цена надежности языка - слож-ость и громоздкость, а генерируемый при этом компилятором код - избыточен и малоэффективен. Открытый язык типа С, основаный на ограниченном количестве базовых идей, обладает большей гибкостью и предоставляет опытному программисту больше возможностей, lll "илучшего языка - для каждого приложения и среды необходимо """ РДства и при этом учитывать квалифика-ИЮ и предпочтения разработчиков. 10.7.2. Язык программирования ADA Первым полным языком программирования в реальном времени является АПд В середине 1970-х годов Министерство обороны СШАдля сокращения расходов на разработку и сопровождение своих систем управления реального времени приняло реще ние ввести единый язык программирования в качестве альтернативы сотням использо-вавщихся тогда языков. В 1979 году министерство одобрило предложения, выдвинутые французской компанией Honeywell ВпП. Язык назван в честь Августы Ады Байрон, графини Лавлейс (Augusta Ada Byron, Countess of Lovelace, 1815-1852), которую можно считать первым программистом в истории - она писала программы для аналитической машины (механического компьютера, который никогда не был построен), спроектированной английским изобретателем Чарльзом Бэббиджем (Charles Babbage). Язык ADA является полной средой разработки программ с текстовым редактором, отладочными средствами, системой управлениями библиотеками и т. д. Спецификации ADA закреплены американским стандартом ANSI/MIL-STD-1815A и включают средства контроля соответствия этому стандарту. Не допускаются дианекты языка -для сертификации компилятор должен правильно выполнить все эталонные тесты. Структура языка ADA похожа на структуру языка Pascal, но его возможности значительно шире, в особенности применительно к системам реального времени. Процессу в ADA соответствует задача, которая выполняет независимо от других задач на выделенном виртуальном процессоре, т. е. параллельно с другими задачами. Задачи могут быть связаны с отдельными прерываниями и исключениями и работать как их обработчики. Новым понятием, введенным в ADA, является пакет - модуль со своими собственными описаниями типов данных, переменных и подпрограмм, в котором явно указано, какие из программ и переменных доступны извне. Пакеты могут компилироваться отдельно с последующим объединением в один исполняемый модуль. Это средство поддерживает модульную разработку программ и создание прикладных библиотек. В начале 1990-х годов язык ADA был пополнен новыми функциями для объектно-ориентированного программирования и программирования в реальном времени. Машинно-ориентированное программирование низкого уровня поддерживается ADA не достаточно эффективно - это следствие постулата, что все задачи решить средствами высокого уровня. Например, для операций ввода/вывода в А используются прикладные пакеты с заранее определенными функциями для управ ления аппаратными интерфейсами и доступа к внешним данным. Основным недостатком ADA является его сложность, которая делает язык тру ным для изучения и применения. Существующие компиляторы являются ящими продуктами и требуют мощных процессоров. До сих пор ADA не полу ожидавшейся популярности, и сомнительно, что это когда-нибудь произойдет. 10.7.3. Языки С и С++ Язык программирования С, несмотря на отсутствие в нем многих средств, кото рые теоретики считают необходимыми для хорошего языка программиров пользуется большим успехом начиная с 1980-х годов по настоящее время. Этот стал популярным для всех приложений, требующих высокой эффективности, в ности для программ реального времени. Для обычных микропроцессоров, испо. смых в системах управления, имеются С-компиляторы и системы разработки мио производителей. В промышленности существует явная тенденция к широкому при-цлению языка С и операционной системы UNIX, которая сама написана на С, по-(.одьку приложения, написанные на С, машинно-независимы и требуют очень небольших усилий для адаптации к работе в различной аппаратной среде. философией С является разбиение программ на функции. С - слаботипизиро-занный язык и позволяет программисту делать почти все вплоть до манипуляции с регистрами и битами. Такая свобода делает язык небезопасным, поскольку компиля-не может проверить, являются ли подозрительные операции умышленными или „ет. Небольшое количество заранее определенных функций и типов данных делает программы легко переносимыми между разными системами. С поддерживает как хороший, структурированный, так и плохой стиль программирования, оставляя ответственность за качество разработки на программисте. Стиль программирования приобретает особое значения при сопровождении программ: плохо написанная и откомментированная программа на С - такая же загадка, как и ассемблерский код. Язык С регламентирован международным стандартом ISO 9899. Язык С предпочтителен для написания программ с обращениями к функциям операционной системы, так как он обладает отличной совместимостью между логикой определения переменных и синтаксисом обращения к системе. Поскольку наиболее распространенные операционные системы в приложениях автоматического управления процессами основываются на UNIX, язык С является почти вынужденным выбором при разработке программ. Почти все примеры в современной технической литературе представлены на С, а для примеров в настоящей книге принят Pascal-подобный синтаксис, поскольку по сравнению с С его легче читать неспециалистам. Язык С++ представляет собой значительно более мощный инструмент, чем С, на основе которого он создан. В С++ значительно улучшена абстракция данных с помощью понятия класса, похожего на абстрактный тип данных с четким разделением между данными и операциями. Классы С++ значительно легче использовать на практике, чем аналогичные понятия в других языках, поскольку С++ поддерживает объектно-ориентированное программирование и поэтапное уточнение типов данных. Главным преимуществом языка С-ы- является его способность поддерживать разработку легко используемых библиотек программ. Программирование в реальном времени непосредственно в С++ не поддерживается, но может быть реализовано с омощью специально разработанных программных модулей и библиотек классов. 0-7.4. BASIC Уров"" является простейшим среди языков программирования высокого 1ро" " создан в 1964 году для поддержки интерактивной разработки MiaMM с удаленных терминалов. Из-за своей простоты BASIC часто критикуется 1тными программистами, и несомненно, что этот язык не является хорошим сред-Цие" создания больших структурированных систем. С другой стороны, неболь-3bj "Р-°ния на BASIC можно разработать значительно быстрее, чем на других ках. Кроме того, BASIC имеется почти на всех мини- и микрокомпьютерах. РР™ BASIC может компилироваться, но чаще она интерпретируется, т. е. 4si команда транслируется в машинные коды только в момент ее выполнения, fi удобен для разработки небольших прикладных задач в составе крупных сис- Но его не следует использовать для приложений порядка 500-1 ООО строк или бо- [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [72] [ 73 ] [74] [75] [76] [77] [78] [79] [80] [81] [82] [83] [84] [85] [86] [87] [88] [89] [90] 0.018 |