Помощь в написании студенческих работ
Антистрессовый сервис

Синхронизация задач. 
Системы реального времени. 
Определения. 
Обзор. Операционные системы

РефератПомощь в написанииУзнать стоимостьмоей работы

Инверсия приоритетов (Priority inversion). Как уже отмечалось, алгоритмы планирования задач (управление доступом к процессорному времени) должны находиться в соответствии с методами управления доступом к другим ресурсам, а все вместе — соответствовать критериям оптимального функционирования системы. Эффект инверсии приоритетов является следствием нарушения гармонии в этой области. Ситуация здесь… Читать ещё >

Синхронизация задач. Системы реального времени. Определения. Обзор. Операционные системы (реферат, курсовая, диплом, контрольная)

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

  • 1. Функции, выполняемые различными задачами, связаны друг с другом. Например, если одна задача подготавливает исходные данные для другой, то последняя не выполняется до тех пор, пока не получит от первой задачи соответствующего сообщения. Одна из вариаций в этом случае — это когда задача при определенных условиях порождает одну или несколько новых задач.
  • 2. Необходимо упорядочить доступ нескольких задач к разделяемому ресурсу.
  • 3. Необходима синхронизация задачи с внешними событиями. Как правило, для этого используется механизм прерываний.
  • 4. Необходима синхронизация задачи по времени. Диапазон различных вариантов в этом случае достаточно широк, от привязки момента выдачи какого-либо воздействия к точному астрономическому времени до простой задержки выполнения задачи на определенный интервал времени. Для решения этих вопросов в конечном счете используются специальные аппаратные средства, называемые таймером.

Давайте рассмотрим все четыре случая более подробно.

Связанные задачи. Взаимное согласование задач с помощью сообщений является одним из важнейших принципов операционных систем реального времени. Способы реализации межзадачного обмена отличаются большим разнообразием, что не в последнюю очередь приводит к обилию терминов в этой области. Можно встретить такие понятия, как сообщение (message), почтовый ящик (mail box), сигнал (signal), событие (event), прокси (proxy) и т. п. Если, читая описание какой-либо ОС РВ, вы встретите уже знакомое название, не спешите делать выводы. Даже один и тот же термин может для разных ОС РВ обозначать разные вещи. Чтобы не запутаться, мы будем в дальнейшем называть сообщениями любой механизм явной передачи информации от одной задачи к другой (такие объекты, как семафоры, можно отнести к механизму неявной передачи сообщений).

Объем информации, передаваемой в сообщениях, может меняться от 1 бита до всей свободной емкости памяти вашей системы. Во многих ОС РВ компоненты операционной системы, так же как и пользовательские задачи, способны принимать и передавать сообщения. Сообщения могут быть асинхронными и синхронными. В первом случае доставка сообщений задаче производится после того, как она в плановом порядке получит управление, а во втором случае циркуляция сообщений оказывает непосредственное влияние на планирование задач. Например, задача, пославшая какое-либо сообщение, немедленно блокируется, если для продолжения работы ей необходимо дождаться ответа, или если низкоприоритетная задача шлет высокоприоритетной задаче сообщение, которого последняя ожидает, то высокоприоритетная задача, если, конечно, используется приоритетная многозадачность с вытеснением, немедленно получит управление.

Иногда сообщения передаются через отведенный для этого буфер определенного размера («почтовый ящик»). При этом, как правило, новое сообщение затирает старое, даже если последнее не было обработано.

Однако наиболее часто используется принцип, когда каждая задача имеет свою очередь сообщений, в конец которой ставится всякое вновь полученное сообщение. Стандартный принцип обработки очереди сообщении по принципу «первым вошел, первым вышел» (FIFO) не всегда оптимально соответствует поставленной задаче. В некоторых ОС РВ предусматривается такая возможность, когда сообщение от высокоприоритетной задачи обрабатывается в первую очередь (в этом случае говорят, что сообщение наследует приоритет пославшей его задачи).

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

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

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

Ресурс — это общий термин, описывающий физическое устройство или область памяти, которые могут одновременно использоваться только одной задачей. Процессорное время тоже представляет собой своеобразный конкурентно используемый ресурс вычислительной системы. Примерам физических устройств могут служить клавиатура, дисплей, дисковый накопитель, принтер и т. п. Представим, например, что несколько задач пытаются одновременно выводить данные на принтер. На распечатке в результате ничего, кроме странной мешанины символов, мы не увидим. В качестве другого примера рассмотрим ситуацию, когда в бортовом компьютере мирно летящего самолета МИГ-29 среди прочих работают две задачи. Одна из них, взаимодействуя с радиолокационной системой, выдаст удаление и направление до цели, а другая задача использует эти данные для пуска ракет класса «воздух-воздух». Не исключено, что первая задача, записав в глобальную структуру данных удаление до цели, будет прервана второй задачей, не успев записать туда направление до цели. В результате вторая задача считает из этой структуры ошибочные данные, что может привести к неудачному пуску со всеми вытекающими отсюда неприятными последствиями. Прервись первая задача чуть позже, и все было бы нормально. Упомянутые здесь проблемы обусловлены времязависимыми ошибками (time dependent error), или «гонками» и характерны для многозадачных ОС, применяющих алгоритмы планирования с вытеснением (кстати, системы с разделением времени также относятся к категории «вытесняющих»).

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

Вот возможные пути решения проблемы.

  • 1. He использовать алгоритмы планирования задач с вытеснением. Это решение, правда, не всегда приемлемо.
  • 2. Использовать специальный сервер ресурса, то есть задачу ответственную за упорядочивание доступа к ресурсу. В этом случае запрос на изменение значения глобальных данных посылается этому серверу в виде сообщения. Аналогичный подход применим и для физических устройств. Так, например, задача может послать данные на печать в виде сообщения, направленного к серверу принтера.
  • 3. Запретить прерывания на время доступа к разделяемым данным. Кардинальное решение, которое, впрочем, не приветствуется в системах реального времени.
  • 4. Использовать для упорядочивания доступа к глобальным данным семафоры. Наиболее часто применяемое решение, которое, впрочем, может привести в некоторых случаях к «инверсии приоритетов».

Последний пункт стоит прокомментировать подробнее, поскольку понятие «семафор» встречается первый раз.

Семафор — это как раз то средство, которое часто используется для синхронизации доступа к ресурсам. В простейшем случае семафор представляет собой байтовую переменную, принимающую значение 0 или 1. Задача, перед тем как использовать ресурс, захватывает семафор, после чего остальные задачи, желающие использовать тот же ресурс, должны ждать, пока семафор (ресурс) освободится. Существуют также так называемые счетные семафоры, где семафор представляет собой счетчик. Пусть к системе подключено три принтера. Семафор, отвечающий за доступ к функциям печати, инициализируется со значением 5, а затем каждый раз, когда какая-либо задача запрашивает семафор для осуществления печати, его значение уменьшается на 1. После завершения печати задача освобождает семафор, в результате чего значение последнего увеличивается на 1. Если текущее значение семафора равно 0, то ресурс считается недоступным, и задачи, запрашивающие печать, должны ждать, пока не освободится хотя бы один принтер. Таким образом может производиться синхронизация доступа множества задач к группе из 3 принтеров. Так как по своей сути семафор также представляет собой глобальную переменную, все неприятности, которые упоминались ранее в связи с самолетом МИГ-29, по идее, должны поджидать нас и здесь. Однако так как работа с семафорами происходит на уровне системных вызовов, программист может быть уверен, что разработчики операционной системы обо всем заранее позаботились.

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

Так как процессы обычно не имеют доступа к данным друг друга, а ресурсы физических устройств, как правило, управляются специальными задачами-серверами (драйверами), наиболее типична ситуация, когда «гонки» за доступ к глобальным переменным устраивают различные потоки, исполняемые в рамках одного программного модуля. Для того чтобы гарантировать, что критическая секция кода исполняется в каждый момент времени только одним потоком, используют механизм взаимоисключающего доступа, или попросту мутексов (Mutual Exclusion Locks, Mutex). Практически мутекс представляет собой разновидность семафора, который сигнализирует другим потокам, что критическая секция кода кем-то уже выполняется.

Критическая секция, использующая мутекс, должна иметь определенные суффиксную и префиксную части. Например:

int global_counter;

void main (void).

{.

mutex_t mutex;

(/* И все это лишь для того, чтобы увеличить глобальную переменную на единицу.*/.

mutexjnit (& mutex, USYNC, NULL);

mutex_lock (& mutex);

global_counter++;

mutex_unlock (& mutex);

}.

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

На этом рассмотрение средств синхронизации доступа к общим ресурсам можно закончить, хотя, разумеется, множество тем осталось за скобками. Например, в WINDOIWS используется, в числе прочего, специальная разновидность мутексов под названием Critical Section Object. Необходимо также помнить, что, кроме ОС, имеющих WINDOIWS или POSIX API. существует большое число ни с чем не совместимых ОС, поэтому наличие средств синхронизации и особенности их реализации должны рассматриваться отдельно для каждой конкретной ОС РВ.

А вот возможные неприятности в борьбе за ресурсы.

Смертельный захват (Deadlock). В народе побочные проявления этой ситуации называются более прозаично «зацикливание» или «зависание». А причина этого может быть достаточно проста — задачи не поделили ресурсы. Пусть, например, Задача, А захватила ресурс клавиатуры и ждет, когда освободится ресурс дисплея, а в это время Задача В также хочет пообщаться с пользователем и, успев захватить ресурс дисплея, ждет теперь, когда освободится клавиатура. Так и будут задачи ждать друг друга до второго потопа. В таких случаях рекомендуется придерживаться тактики «или все, или и ничего». Другим и словами, если задача не смогла получить все необходимые для дальнейшей работы ресурсы, она должна освободить всё, что уже захвачено, и, как говорится, «зайти через полчаса». Другим решением, которое уже упоминалось, является использование серверов ресурсов.

Инверсия приоритетов (Priority inversion). Как уже отмечалось, алгоритмы планирования задач (управление доступом к процессорному времени) должны находиться в соответствии с методами управления доступом к другим ресурсам, а все вместе — соответствовать критериям оптимального функционирования системы. Эффект инверсии приоритетов является следствием нарушения гармонии в этой области. Ситуация здесь похожа на «смертельный захват», однако сюжет закручен еще более лихо. Представим, что у нас есть высокоприоритетная Задача А, среднеприоритетная Задача В и низкоприоритетная Задача С. Пусть в начальный момент времени Задачи, А и В блокированы в ожидании какого-либо внешнего события. Допустим, получившая в результате этого управление Задача С захватила Семафор А, но не успела она его отдать, как была прервана Задачей А. В свою очередь, Задача, А при попытке захватить Семафор, А будет блокирована, так как этот семафор уже захвачен Задачей С. Если к этому времени Задача В находится в состоянии готовности, то управление после этого получит именно она, как имеющая более высокий, чем у Задачи С, приоритет. Теперь Задача В может занимать процессорное время, пока ей не надоест, а мы получаем ситуацию, когда высокоприоритетная Задача, А не может функционировать из-за того, что необходимый ей ресурс занят низкоприоритетной Задачей С.

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

  • 1. Стремление обеспечить максимально быструю и детерминированную реакцию системы на внешнее событие.
  • 2. Старание добиться минимально возможных периодов времени, когда в системе запрещены прерывания.
  • 3. Подпрограммы обработки прерываний выполняют минимальный объем функций за максимально короткое время. Это обусловлено несколькими причинами. Во-первых, не все ОС РВ обеспечивают возможность «вытеснения» во время обработки подпрограмм прерывания. Во-вторых, приоритеты аппаратных прерываний не всегда соответствуют приоритетам задач, с которыми они связаны. В-третьих, задержки с обработкой прерываний могут привести к потере данных.

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

Синхронизация по времени. Совсем не так давно (лет 20 назад) аппаратные средства, отвечающие в вычислительных системах за службу времени, были совершенно не развиты. В те приснопамятные времена считалось достаточным, если в системе генерировалось прерывание с частотой сети переменного тока. Те же, кто не знал, что частота сети в США 60 Гц, а не 50, как у нас, постоянно удивлялись тому, что системное время в RSX-11 М никогда не бывает правильным. Программисты для получения задержек по времени часто использовали программные циклы ожидания и, разумеется, пользователи таких программ получали массу сюрпризов при попытке их переноса на следующее поколение компьютеров с более высокими тактовыми частотами. Благодаря научно-техническому прогрессу, сейчас любой мало-мальски приличный компьютер имеет часы/календарь с батарейной поддержкой и многофункциональный таймер (а то и несколько) с разрешением до единиц микросекунд.

Как правило, в ОС РВ задается эталонный интервал (квант) времени, который иногда называют тиком (Tick) и который используется в качестве базовой единицы измерения времени. Размерность этой единицы для разных ОС рв может быть разной, как, впрочем, разными могут быть набор функций и механизмы взаимодействия с таймером. Функции по работе с таймером используют для приостановки выполнения задачи на какое-то время, для запуска задачи в определенное время, для относительной синхронизации нескольких задач по времени и т. п. Если в программе для ОС РВ вы увидите операнд delay (50), то, скорее всего, это обозначает, что в этом месте задача должна прерваться (блокироваться), а через 50 мс возобновить свое выполнение, а точнее, перейти в состояние готовности. Все это время процессор не простаивает, а решает другие задачи, если таковые имеются. Множество задач одновременно могут запросить сервис таймера, поэтому если для каждого такого запроса используется элемент в таблице временных интервалов, то накладные расходы системы по обработке прерываний от аппаратного таймера растут пропорционально размерности этой таблицы и могут стать недопустимыми. Для решения этой проблемы можно вместо таблицы использовать связный список и алгоритм так называемого дифференциального таймера, когда во время каждого тика уменьшается только один счетчик интервала времени.

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

Показать весь текст
Заполнить форму текущей работой