Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Операционные системы реального времени и технологии разработки кроссплатформенного программного обеспечения. Ч.1. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
2.1. Основные определения
21
Рис. 1. Жизненный цикл процесса в системе
Процесс переходит в состояние готовности и ожидает вызова на вы-
полнение.
Отправка на выполнение (process dispatch) происходит тогда, когда
микропроцессор может выполнить этот процесс и для него сформированы начальные условия.
Планировщик также может запомнить этот процесс и его окружение для вызовов в будущем. Окружение процесса подразумевает хранение состо­яния регистром микропроцессора, состояния регистра флагов и другой си­стемной информации в специальных сегментах и разделах памяти. Окруже­ние процесса записывается в тот момент, когда процесс “ставится на паузу” и читается (восстанавливается) в момент запуска процесса. Это позволяет за­пустить процесс снова фактически “с того места”, когда он был остановлен.
Также следует отметить, что процесс может быть заменен в очереди на выполнение более приоритетным процессом и тогда он будет просто от­ложен в состоянии “готовности”.
Остановка процесса (timeout) выполняется в основном как следствие одного из двух событий: процесс превысил выделенный ему квант времени на выполнение или процесс был прерван по сигналу внешнего или внут­реннего прерывания. В этом случае у прерванного процесса остается состо­яние “готовности”, окружение будет храниться в специальном сегменте, и он будет ожидать нового запуска со стороны планировщика.
2. Основные положения
22
Блокировка (blocking) процесса осуществляется специальным си-
стемным вызовом – запросом операционной системы, который должен быть немедленно удовлетворен перед тем, как заблокированный процесс продолжит свою работу. Обычно это происходит при выполнении доступа к общим ресурсам или при поступлении запроса на ввод-вывод. В таком случае ОС инициирует отдельную процедуру блокировки для удовлетворе­ния запроса. Примером может служить необходимость доступа к файлу на внешнем носителе. Тогда ОС формирует сигнал для диска, инициализиру­ющий функцию чтения или записи блока данных. Процесс переводится в заблокированное состояние, пока действие не будет закончено и возобнов­ляется по завершению действия.
Разблокирование процесса (unblocking) происходит в обратном по­рядке относительно блокировки. Когда ресурс или запрос блокирует про­цесс, а потом блокирующее действие заканчивается, обычно формируется другой сигнал или прерывание, сообщающее планировщику, что можно вновь выполнять заблокированный процесс. Тогда процесс помечается как готовый к вызову и в вновь помещается в очередь на выполнение.
Такой цикл может выполняться до тех пор, пока система не прекра­тит нуждаться в данном процессе, если это произошло, то процесс оконча­тельно уничтожается.
Уничтожение (termination) процесса может быть нормальным (normal) или экстренным (abnormal). Последний вариант иногда называется исключением (exception). В любом случае, система освобождает все зани­маемые процессом ресурсы, а в случае исключения или экстренного завер­шения, ОС обычно вырабатывает специальный сигнал и делает запись в потоке (файле) ошибок. Это исключение можно перехватить программно или аппаратно и принять определенные меры. Этот прием часто использу­ется в программировании при помощи конструкций try/cache/finally и поз­воляет существенно повысить устойчивость программного обеспечения. Грамотный программист размещает подобные конструкции во всех местах программы, которые могут вызвать исключение или ненормальное завер­шение процесса. Примерами могут служить операции деления, обращение к объектам и ресурсам, которых может не существовать, преобразование сложных структур данных.
2.1. Основные определения
23
Исключения, или, другими словами, исключительные ситуации, это
события, возникающие при попытке сделать что-то недопустимое. Это син­хронные события. Они возникают в контексте текущей выполняемой за­дачи и могут быть исправимыми или неисправимыми.
Согласно статистике, исправимые исключения – это нормально. Бо-
лее того, в некоторых случаях даже приходится встраивать исправимые ис­ключения в программу специально. В других ситуациях только исключе­ния помогают проанализировать выполнение программы (например, подо­брать декодер для данных неизвестного формата) и правильно выполнить алгоритм. Звучит странно, но это так.
После реализации или обхода исправимого исключения, программа
продолжает дальнейший ход работы без каких-либо нарушений.
Неисправимые исключения – это совсем другая история. Обычная
реакция операционной системы на неисправимое исключение – аварийное завершение программы. Поэтому ОС на своем уровне должна обеспечивать перехват подобных ситуаций и не допускать собственное “падение” даже в случае “падения” программы.
В некоторых случаях требуется обеспечить взаимодействие между процессами для передачи данных или управляющих команд. Эти процессы могут выполняться “квазипараллельно” на последовательных системах или действительно параллельно на многоядерных или многопроцессорных си­стемах, а также могут запускаться в определенной последовательности в соответствии с каким-либо алгоритмом. В любом случае, ОС РВ должна иметь механизмы взаимодействия процессов.
Самыми распространенными методами и инструментами взаимо­действия являются следующие.
1. Разделяемая между процессами область памяти. Данная ситуация
наблюдается тогда, когда два или более процесса имеют доступ к одной области памяти или даже к одной переменной в памяти, но каждый в свое время. В случае реальной памяти такой доступ контролируется специаль­ной микросхемой – арбитром, а в случае виртуальной памяти – ОС и мик­ропроцессором, так как нужно обеспечить отображение нескольких разных областей виртуальной памяти на единственное реальное адресное про­странство.
2. Основные положения
24
2. Система семафоров. Семафор – это флаг, признак. Некоторые
данные, которые имеют два стабильных состояния (логический нуль и ло­гическая единица). Сама по себе переменная находится в специальной си­стемной области памяти и доступ к ней регулируется посредством специ­альных функций и поддерживается операционной системой.
3. Система сигналов. Сигналы – это формализованные сообщения
стандартного вида, которые доставляются посредством служебных каналов связи от одного процесса к другому. Процессы имеют обработчики подоб­ных событий и регистрируют их в операционной системе для того, чтобы была возможность отреагировать на сигнал. Часто такой механизм приме­няется для оповещения о сбоях и исключениях или об аппаратных преры­ваниях. Наиболее ярким примером среди программных систем может слу­жить принцип сигналов/слотов в C++/Qt. Такое взаимодействие реализу­ется между компонентами даже внутри одной программы.
4. Почтовые ящики. Ящик – это очередь сообщений, который до-
ступен многим процессам. Каждый процесс, которому нужно передать дан­ные другому процессу, размещает свое сообщение в ящик. Все процессы имеют доступ к этому ящику и периодически “читают почту”. При получе­нии “своего” письма, процесс активизирует одно из своих состояний и начинает работу.
Все подобные механизмы объединяет одно понятие – событие.
Под событием будем понимать факт оповещения процесса со сто­роны ОС или другого процесса о возникновении некоторой ситуации, на которую у процесса есть описанная стандартная реакция. Индикатором со­бытия может служить что угодно: получение сообщения, сигнал, измене­ние состояния семафора и т.п.
Наиболее важными событиями в системе являются прерывания.
Под прерыванием будем понимать некоторое событие, преимуще­ственно аппаратное, на которое нужно немедленно реагировать. Прерыва­ния могут быть штатными или внештатными. Штатные или стандартные прерывания – это нормальные регулярные или случайные сигналы, кото­рые возникают при нормальном выполнении программ и алгоритмов и в условиях нормальной работы аппаратуры. Внештатные или экстренные прерывания возникают в случае ошибок и сбоев, при нарушении границ ожидания окончания процессов, превышении числа попыток чтения ин­формации с внешнего источника и т.п.
2.1. Основные определения
25
Прерывания можно разделять на программные и аппаратные. Про-
граммные прерывания могут быть вызваны процессами или самой опера­ционной системой, могут быть следствием аппаратных прерываний, и мо­гут означать штатное или внештатное завершение каких-либо работ и зада­ний, а также разные внештатные ситуации. Аппаратные прерывания в первую очередь возникают на уровне “железа” и потом отображаются в слой программного обеспечения. Это могут быть сигналы от внешних ис­точников, датчиков, компьютерных сетей, таймеров, счетчиков, блоков пе­редачи данных и т.п.
Прерывания могут быть синхронными и асинхронными. Синхрон-
ные прерывания наблюдаются только на участках систем с жестким тай­мингом. Здесь имеется в виду то, что события, вызывающие прерывания, происходят регулярно, но с определенной частотой. Практически в ста про­центах случаев эти события управляются таймерами и счетчиками. Асин­хронные или апериодические прерывания возникают в случайном порядке и их никак нельзя запланировать.
Каждое прерывание имеет свой тип, а следовательно, и номер. Ко-
личество возможных номеров прерываний зависит от системы, ее прин­ципа работы и архитектуры. Раньше было возможно иметь всего 256 номе­ров прерываний и 256 обработчиков соответственно. Это обусловлено ограничением объема таблицы “векторов” прерываний размером 1 Кб. В более поздних системах уже использовалась не таблица прерываний, а дескрипторные таблицы и теперь номеров прерываний может быть, факти­чески, сколько угодно.
В любом случае, известный номер прерывания позволяет заранее подготовить обработчик именно этого конкретного прерывания и оставить его в системе в состоянии готовности. Этот обработчик и будет вызван по своему номеру, так как этот номер зарегистрирован в специальных табли­цах и однозначно поставлен в соответствии адресу начала выполняемого программного кода.
Прерывание – это порой единственный способ обмена информацией между процессами, единственный способ для одной системы сообщить другой системе о чем-то важном. Поэтому прерывания, особенно аппарат­ные, это самые приоритетные события для ОС РВ. В таких ОС стараются
2. Основные положения
26
уменьшить не только время отклика на событие, но и время переключения контекста задачи, являющейся реакцией на событие.
Из концепции прерываний родилась современная технология собы-
тийно-ориентированного программирования. Этот принцип работы осно­вывается на том, что в системе отсутствует большая часть привычных эле­ментов, зато присутствует множество программных модулей, работающих именно как реакция на событие. После своего завершения, такие процессы вызывают срабатывание триггера, который может являться событием для запуска следующей реакции. Таким образом, здесь отсутствует прямая пе­редача управления между программными компонентами – все основыва­ется на триггерах, событиях и на реакциях.
Под потоком или “нитью” будем понимать ветвление основного
процесса, т.е. когда задача, реализуемая каким-либо процессом, нуждается в ветвлении своего исполняемого кода, она может породить дополнитель­ные потоки, несущие в себе отдельные участки общего алгоритма работы родительского процесса.
Иногда родительский процесс может быть всего лишь началом или отправной точкой для целой системы порождаемых потоков. При этом каж­дый поток может реализовывать свой собственный алгоритм, а может быть копией других потоков, разве что с некоторыми изменениями.
В любом случае:
поток будет разделять область физической памяти для кода и данных вместе с процессом;
поток будет иметь свой собственный стек;
поток будет разделять область виртуальной памяти вместе с про-
цессом;
поток имеет свое собственное состояние.
У двух потоков, запущенных в одном процессе, вся память является разделяемой.
Потоки могут быть классифицированы следующим образом:
циклические задачи, выраженные в потоках;
периодические задачи, выраженные в потоках;
импульсные задачи, выраженные в потоках.
Циклические задачи характерны для процессов управления так же, как и периодические. Они переходят из одного состояния в другое через
2.1. Основные определения
27
строго заданный промежуток времени в пределах определенного цикла. За­пуск может также выполняться несколько раз за один цикл в зависимости от количества меток или счетчика запусков. Такие задачи имеют самые жесткие ограничения на время отклика и время выполнения.
Апериодические или асинхронные задачи, относящиеся к классу им­пульсных, обычно имеют минимальный приоритет в системе и могут быть отложены или прерваны другими задачами. Обычно это задачи диагно­стики, сохранения или обновления информации о внешней среде или же задачи сбора статистики.
У апериодических задач есть разновидности, называемые споради­ческими. Это апериодические задачи с крайне жестким временем выполне­ния и сроком исполнения. Зачастую спорадические задачи имеют стохасти­ческую природу и сложно прогнозируемы.
Фоновые задачи – это задачи, для которых не устанавливается край­ний срок исполнения. Они выполняются в основном во время простоя про­цессора, так как не являются приоритетными.
Аппендиксные задачи – это задачи, которые чаще всего выполня­ются до старта микропроцессора. Они служат для подготовки системы к запуску и выполнения первичных настроек.
Под ресурсом будем понимать некоторые объекты, которые необхо­димы для функционирования программ или аппаратных модулей. Это мо­гут быть:
ресурсы микропроцессора и заложенные в него аппаратно-под- держиваемые алгоритмы;
области памяти;
периферийные устройства;
отдельные программные модули;
наборы данных;
файлы;
сообщения;
прерывания и их обработчики.
Кроме данной классификации, также существует разделение ресур­сов по следующим категориям.
1. Активные ресурсы: ресурсы, которые сами могут изменять дан-
ные (чаще всего это микропроцессор и его алгоритмы).
2. Основные положения
28
2. Пассивные: это ресурсы, которые способны только хранить дан-
ные между своими состояниями.
3. Локальные: это ресурсы, принадлежащие одному процессу, но их
время жизни не может превышать время жизни этого процесса.
4. Постоянные: это ресурсы, которые не меняют свое содержимое
между состояниями и могут быть “захвачены” или “освобождены”.
5. Временные: это ресурсы, которые существуют или доступны
только ограниченное время.
6. Критичные: это ресурсы, которые могут быть использованы
только одним процессом. Пока этот процесс не закончит работать с ресур­сом, последний не станет доступным другим процессам.
7. Не критичные: это ресурсы, которые могут быть использованы
разными процессами.
Под приоритетом будем понимать важность процесса, выражаемого
в виде числа, присваиваемого этому процессу. Зная это число, планиров­щик может формировать очередь выполнения задач и запуска процессов, переставляя их согласно номерам. Обычно, чем больше число, отражающее приоритет, тем важнее процесс. В начале очереди будут находиться про­цессы с высоким приоритетом. Из этого принципа следует, что некоторые низкоприоритетные процессы могут вообще не быть выполнены. Для ре­шения этой проблемы существуют алгоритмы ротации приоритетов и сдвига приоритетного кольца.
Под параллельными процессами будем понимать одновременно ра-
ботающие потоки и процессы, реализующие один и тот же алгоритм (или разные алгоритмы), и запущенные в одно и то же (или в разное) время. Воз­можность запуска параллельных процессов зависит от возможностей аппа­ратуры и возможностей операционной системы.
Если запущено сразу несколько процессов, то можно говорить о том,
что система является многозадачной.
Таким образом, если микропроцессор один и имеет одно ядро, то си-
стема в любом случае будет однозадачной. В таком случае может сработать метод переключения задач, т.е. их последовательный запуск в пределах кванта времени, достаточного для того, чтобы внешние системы или поль­зователи подумали, что одновременно запущено несколько процессов.
2.2. Типы взаимодействия процессов
29
Этот подход в большей степени характерен для обычных операци­онных систем, так как в ОС РВ более жесткие рамки, а переключение задач в некотором роде обладает стохастической (вероятностной) природой.
Под связыванием будем понимать процесс превращения скомпили­рованного кода в загрузочные модули. Скомпилированные модули иногда называют объектными модулями, а загрузочные модули – исполняемым кодом, поддерживаемым со стороны операционной системы.
Можно различать статическое и динамическое связывание.
Статическое связывание фактически подразумевает прямую вставку кода необходимых программ или библиотек в те объектные модули, кото­рые в этом нуждаются.
Динамическое связывание подразумевает встраивание ссылок на код библиотечных функций вместо прямой вставки. Сам вставляемый код будет выполнен непосредственно при выполнении модуля со ссылками.
Логично, что каждый из этих подходов имеет свои достоинства и не­достатки. Недостатком статического связывания является большой объем кода, а достоинством – меньшее время выполнения по сравнению с дина­мически связанным модулем. Достоинство динамического связывания оче­видно – меньший объем модулей, а недостаток обратный – увеличивается время выполнения за счет вызовов кода по ссылкам.
Динамическое связывание часто используется в современной разра­ботке программного обеспечения, когда необходимо защитить программ­ной лицензией и сделать его нечитаемым или неизменяемым другими мо­дулями и программами.
2.2. Типы взаимодействия процессов
Процессы по типу взаимодействия разделяют:
на сотрудничающие;
конкурирующие.
Сотрудничающие процессы разделяют коммуникационный канал, выполняют взаимную синхронизацию. Конкурирующие процессы исполь­зуют критическую секцию, совместно разделяемые ресурсы, а также вза­имные исключения.
2. Основные положения
30
В критической секции запрещается переключение задач. Это дела­ется для того, чтобы процесс пользовался исключительным правом на ис­пользование ресурсов. Каждая ОС РВ может предоставлять своим про­цессам право войти в критическую секцию и выйти из нее посредством системных вызовов. Единственным здесь требованием является мини­мальное время нахождения в критической секции, иначе могут быть нару­шены ограничения на время реакции и скорость обработки внешних со­бытий. Естественно, что во время нахождения какого-либо процесса в критической секции, операционная система “собирает” прерывания в спе­циальную очередь для того, чтобы обработать их позже, при выходе из критической секции.
Взаимное исключение для процесса – это особый способ синхро­низации нескольких работающих параллельно процессов, которые ис­пользуют разделяемый ресурс. Если этот процесс кем-то занят, то он пе­реводится в состояние ожидания, и ОС генерирует системный вызов для освобождения ресурса. После возвращения ресурса, процесс опять от­правляется на выполнение, но уже с доступом к требуемому ресурсу. Ре­сурс теперь имеет пометку “занят”, которая останется за ним до момента освобождения.
Если несколько параллельных процессов независимы, т.е. не ис­пользуют ресурсы совместно, то дополнительная синхронизация для них не требуется.
Примером может являться общая память, а точнее ее одна или не­сколько областей. Если процессы работают в разном адресном простран­стве, то они независимы. В противном случае, между процессами возни­кает конкуренция: одному процессу может понадобиться записать что­либо по адресу в память, а другому – прочитать данные с этим же адресом.
При синхронизации процессов операционной системе необходимо решать сразу три проблемы.
1. Блокировка (lockout).
2. Тупик (deadlock).
3. Голодовка (starvation).
Блокировка возникает тогда, когда процесс, решающий какую-либо задачу, ожидает ресурс, который никогда не освободится. В этом случае процесс может быть навсегда заблокирован ресурсом.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]