Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Операционные системы реального времени и технологии разработки кроссплатформенного программного обеспечения. Ч.1. Учебное пособие
.pdf
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).
Блокировка возникает тогда, когда процесс, решающий какую-либо
задачу, ожидает ресурс, который никогда не освободится. В этом случае
процесс может быть навсегда заблокирован ресурсом.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
