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

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

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
5.3. Современные механизмы синхронизации потоков
91
Ресурс, который предоставляется монопольно только одному из
многих процессов, называется “критическим ресурсом”. Современные ОС РВ предоставляют несколько стандартных объектов синхронизации:
критический раздел; мьютекс; семафор;событие.
Все они, кроме критического раздела, являются объектами ядра опе-
рационной системы и обрабатываются инструментами ядра.
Как и во многих других случаях, для обеспечения взаимодействия
между задачами и их синхронизацией, строят ряд очередей:
очередь выполняемых задач; очередь готовых задач; очередь задач в ожидании семафора; очередь задач в ожидании события.
Очередь выполняемых задач состоит из задач, которые находятся в
состоянии исполнения, т.е. получающих рабочее время и ресурсы процес­сора в соответствии с тем или иным алгоритмом.
Очередь готовых задач принимает в себя задачи, которые находятся
в состоянии готовности.
Очередь задач в ожидании семафора строится для каждого создан-
ного семафора в системе.
Очередь задач в ожидании события, аналогично предыдущей, стро-
ится для каждого созданного в системе события.
Все эти очереди относятся к базовым очередям. На их основе стро­ятся другие очереди. Например, очередь для отправки писем и сообщений строятся на базе очередей семафоров и событий: одна очередь создается для хранения сообщений для отправки, другая очередь – для сообщений, которые ждут освобождения места в почтовом ящике.
Очереди любого типа создаются и обслуживаются либо операцион­ной системой, либо аппаратно. Поэтому все операции с очередями приво­дят к системным вызовам. Каждый вызов проходит в ядро системы и в ме­неджер задач и памяти, поэтому использование очередей сопряжено с до­полнительными расходами.
5. Синхронизация и взаимодействие процессов
92
Еще одним рассмотренным ранее механизмом синхронизации явля­ется критический раздел или критическая секция. Это некоторый объект, к которому происходит обращение потока перед получением монопольного доступа к какому-нибудь ресурсу. Критический раздел достаточно просто организовать, например, по сравнению с очередью, потому что синхрони­зуемые объекты принадлежат к одному процессу. Эта особенность приво­дит к тому, что в одно и то же время только один поток получает доступ к определенному классу (региону, области) ресурсов. Критический раздел и обслуживающие его программные средства анализируют значение специ­ального параметра процесса (флага), который предотвращает, например, исполнение одного участка кода разными потоками одновременно или из­менение одного элемента данных в разных задачах.
Следующим рассмотренным методом синхронизации является ис­пользование семафоров.
Модель семафоров была предложена голландским ученым Дейкстройном и основывается на том, что в систему вводится специальная модель данных, называемых семафорами. Переменная типа семафор имеет целочисленный тип и на ней разрешено только два типа операций:
опустить (Down);
поднять (Up).
Объекты типа семафор применяются для контроля и учета ресурсов в целях ограничения доступа к этим ресурсам со стороны сразу нескольких потоков. Введя семафоры в систему, можно организовать работу программ таким образом, что доступ к ресурсам будет разрешен сразу от имени не­скольких потоков, но их число будет ограничено. Значение переменной се­мафора как раз и говорит о том, какое максимальное количество потоков могут работать с ресурсом.
Если в какой-то момент времени с ресурсом работает меньшее число потоков, чем указано в семафоре, то семафор будет находиться в так назы­ваемом “сигнальном” состоянии. Как только число потоков превышает зна­чение, указанное в переменной семафора, он перекачается в состояние за­прета и доступ большего количества ресурсов блокируется.
Операция “опустить” семафор применяется для контроля ресурсов и ограничения одновременного доступа к ресурсу со стороны нескольких
5.3. Современные механизмы синхронизации потоков
93
потоков. Применяя семафор, можно устроить работу программ таким об­разом, что к одному определенному ресурсу смогут обращаться только ограниченное число потоков. Как только число работающих с ресурсом потоков достигнет предела, доступ будет заблокирован. Применение опе­рации “опустить” семафор производится как инкремент значения (увели­чение на единицу).
Операция “поднять” семафор вызывает его проверку и, если значе-
ние семафора больше нуля, то производится его декремент (т.е. уменьше­ние счетчика на единицу).
Здесь важно понимать, что операции с семафором похожи на тран-
закции в базе данных. Это значит, что они проводятся от начала и до конца без прерывания процесса. Они могут называться атомарными.
Семафор, который может принимать только два значения: ноль или единица, называется бинарным или двоичным. Захват семафора вызывает его переключение в другое состояние, а все остальные задачи будут ждать его возврата в исходное значение.
Другое применение счетчиков – семафоров, которые могут прини­мать больше двух значений, можно описать следующим образом. Допу­стим, в системе есть множество устройств вывода информации, например, принтеры количеством 3 (три) штуки. Семафор устройств инициализиру­ется со значением 3 (три) и каждый раз, когда некоторая задача делает за­прос к семафору для печати документа, значение семафора декрементиру­ется. После завершения печати семафор освобождается и его значение ин­крементируется. Если текущее значение семафора нулевое, то ресурс счи­тается недоступным, пока его значение не станет отличным от нуля. Это состояние эквивалентно состоянию освобождения очереди печати для трех устройств.
Семафоры являются достаточно эффективным решением для син­хронизации процессов и задач, однако программирование с учетом сема­форов – это сложный процесс, сопряженный с решением многих задач. Лю- бая ошибка может привести к рассинхронизации процессов, к образованию тупиковых ситуаций и даже к сбоям.
С целью облегчить труд разработчиков, применяются другие спо­собы синхронизации и дополнительные инструменты.
5. Синхронизация и взаимодействие процессов
94
5.4. Мониторы
Идея мониторов была предложена Хоаром в 1974 г. В отличие от
других способов синхронизации, монитор в данном контексте представ­ляет собой некоторую конструкцию на языке программирования, т.е. про­граммный инструмент, поддерживаемый на уровне компиляции программ, а значит предоставляемый на уровне языка программирования.
Монитор являет собой совокупность процедур и библиотечных
функций, а также структур данных, компилируемых в специальный про­граммный модуль.
Для мониторов выделяют три основных свойства или условия.
1. Входящие в монитор структуры данных доступны только для тех
процедур, которые входят в данный монитор, т.е. монитор представляет со­бой некоторый вариант объекта (как в объектно-ориентированных языках программирования) и реализует сокрытие (т.е. инкапсуляцию) данных.
2. Любой процесс может войти в монитор после вызова одной из
его процедур.
3. В любой момент в монитор входит не более одного процесса,
если есть несколько процессов, которым необходимо попасть в уже заня­тый монитор, то монитор блокируется. Таким образом, если необходимо, например, обеспечить защиту разделяемых данных, то можно просто поме­стить их внутрь монитора вместе с критическими секциями обслуживаю­щих их процедур.
Компилятору языка программирования, в котором существуют про-
граммные конструкции мониторов, известно, что входящие в них проце­дуры имеют определенную, выделяющуюся из общей массы семантику. Поэтому уже после проверки первого же условия (см. список выше) про­граммы непосредственно на этапе компиляции, становится известно, явля­ется ли данный участок кода монитором или нет. Также можно спокойно обеспечить выполнение третьего свойства или условия существования мо­нитора (прием только одного процесса).
Монитор является достаточно надежным инструментом синхрони-
зации, так как:
он имеет определенную структуру; формируется компилятором;
5.4. Мониторы
95
обслуживается языком программирования;
большинство ошибок могут быть обнаружены компилятором и
не попадут в финальную сборку программы.
Помимо обычных структур данных, мониторы могут включать в себя определенные специальные переменные, содержащие в себе опера­торы условий (например, wait или signal).
Эти переменные являются дополнительным инструментом синхро­низации помимо основных алгоритмов.
Если процесс, входящий в монитор и исполняющий одну из проце­дур монитора, обнаруживает, что он не может продолжать свою работу в силу ряда определенных причин (например, до сих пор не готово внешнее устройство, буфер данных переполнился, другая функция не обновила дан­ные в разделяемом ресурсе и т.д.), то он вызывает выполнение особой опе­рации wait с отдельной переменной или условием. Дальнейшее выполнение текущего процесса в мониторе блокируется, пока операция wait не завер­шится, т.е. не закончится ожидание окончания блокирующего события.
С другой стороны, если некоторый процесс производит действия, которые могут снять блокировку выполнения основной операции мони­тора, вызванной командой wait, то он должен вызвать команду signal для разблокировки.
То есть, другими словами, если один процесс Х ожидает чего-то от процесса Y в мониторе с командой wait, то процесс Y, закончив операцию, должен фактически уведомить процесс Х об этом событии.
Тонкость данных манипуляций заключается в том, что, как следует из самого определения монитора, только один процесс может занимать мо­нитор. А в описанном выше примере участвует два процесса.
Создатель технологии мониторов описал эту ситуацию следующим образом: если процесс, вызвавший signal, приостанавливается, то в мони­тор может войти процесс, ожидающий сигнал завершения с командой wait.
В 1975 г. было получено более простое описание данной ситуации: вызов команды signal должен быть последним внутри процедуры монитора (должен быть последней командой), чтобы процесс покинул монитор сразу после вызова сигнала.
Основное достоинство мониторов заключается в том, что взаимное исключение здесь возникает автоматически, так как в одно время только
5. Синхронизация и взаимодействие процессов
96
один процесс находится на выполнении в мониторе. Это очень сильно упрощает процесс программирования и проектирования программ.
Пожалуй, единственным недостатком мониторов является то, что это не отдельная технология, а программная конструкция. Следовательно, мониторы доступны только там, где есть возможность программировать на соответствующем языке, ну или на крайний случай, использовать такой язык для вызова библиотечных функций. Следует помнить, что такие языки редки и специфичны.
Семафоры, в отличие от монитора, являются средствами и атрибу­тами самой операционной системы. Следовательно, если программист хо­чет поддерживать семафоры в своих программах, то он может это сделать вне зависимости от какого-либо языка программирования.
5.5. Обмен сообщениями
Для семафоров и мониторов характерна одна и та же проблема. Их реализация опирается на постулат о том, что мы используем однопроцес­сорную систему или многопроцессорную систему, где все процессы имеют доступ к общей памяти.
В том случае, когда память системы распределена, и каждый процес­сор имеет доступ только к своей области памяти, семафоры и мониторы в чистом виде не подходят.
Следовательно, для подобных систем нужно более гибкое и мощное решение.
Таким инструментом является обмен сообщениями.
Сейчас обмен сообщениями применяется практически во всем при­кладном программном обеспечении коммерческого уровня, реализуется на базе локальных и сетевых кэшей и корпоративных шин обмена информа­цией. Однако первоначально механика обмена сообщениями применялась исключительно в операционных системах реального времени.
Обмен сообщениями в рассматриваемом варианте – это отличный инструмент синхронизации. На его основе можно реализовывать и меха­низм взаимных исключений, и конкурентный доступ к ресурсу, и простой обмен информацией между связанными процессами.
5.5. Обмен сообщениями
97
Рассмотрим обобщенный пример применения системы обмена сооб-
щениями и его основную концепцию.
Допустим, у нас есть несколько программных агентов, между кото-
рыми необходимо провести синхронизацию и обмен данными.
Следовательно, в самом простом случае, программные агенты
должны иметь доступ к шине для обмена сообщениями и как минимум две реализации стандартных процедур:
отправка сообщения; прием сообщения.
Дополнительно к этим двум функциям, конечно, реализуют функ-
ции ожидания сообщения (методом опроса или методом сигналов) и функ­ции разбора сообщений с анализом адреса сообщения.
Как и семафоры, эти процедуры реализуются системными вызовами,
а не конструкциями конкретного языка программирования.
Система сообщений обладает следующими стандартными характе-
ристиками.
1. Способ синхронизации.
2. Метод адресации.
3. Длина сообщения (минимальная и максимальная).
Рассмотрим их последовательно. Способ синхронизации в системе сообщения подразумевает сам
смысл и содержание обмена данными, оформленными в виде отдельных па­кетов – сообщений. Пакет выпускает источник, а принимает один или не­сколько приемников сообщений. Если приемник один, и он определен зара­нее – сообщение считается адресным. Если приемников несколько, и их со­став определен заранее – сообщение считают групповым. Если принимают сообщения все приемники – сообщение считают широковещательным.
Весь процесс трансляции сообщений прост и функционален: один источник формирует сообщение, помещает его в очередь, которую “слу­шают” приемники. Однако иногда возникает ситуация, когда некоторый приемник ожидает сообщение, а передатчик его не посылает, или наоборот – передатчик отправляет сообщение, которое некому принимать или при­емник еще не готов к приему. В этом случае, как операция передачи, так и операция приема могут быть блокирующими или неблокирующими. Для операции отправки (send) это означает, что процесс – отправитель может
5. Синхронизация и взаимодействие процессов
98
быть заблокирован до того момента, пока процесс – приемник напрямую не вызовет операцию receive. В исключительных случаях, отправка сообще­ния производится независимо от наличия получателя в системе (тогда сооб­щение “оседает” в очереди до появления получателя). Для операции приема receive это означает, что операция получения возникает ранее, чем фактиче­ски было послано сообщение – в этом случае она блокируется до самого со­бытия получения сообщения с последующим возвратом управления.
В связи с этим существует несколько схем и комбинаций операций
отправки и получения:
схема рандеву; неблокирующая отправка и блокирующий прием; неблокирующая отправка и неблокирующий прием.
Схема рандеву подразумевает, что процедура отправки является
блокирующей так же, как и операция приема. Они не требуют буферизации сообщений и часто применяются именно как элемент синхронизации.
Неблокирующая отправка и блокирующий прием возникают тогда, когда реализуется схема работы типа клиент/сервер. Здесь серверный про­цесс блокируется до тех пор, пока не возникнет очередной запрос для об­работки. В это время клиент, пославший запрос к серверу, может продол­жить свое выполнение, не ожидая фактического окончания обработки сво­его запроса на сервере.
Неблокирующая отправка и неблокирующий прием наблюдается то­гда, когда оба процесса могут продолжать свое выполнение, не дожидаясь окончания коммуникации между собой.
Здесь очень важно понимать, что в том случае, когда отправка явля­ется неблокирующей, процесс, отправивший сообщение, не имеет инфор­мации о том, получено и обработано ли без ошибок его сообщение. Это происходит потому, что ответа от получателя отправитель не имеет.
В данном случае можно говорить о “гарантированной” доставке со­общений, когда есть какая-либо обратная связь и отправитель получает ин­формацию о получении сообщения адресатом. Такой механизм основыва­ется на дополнительной подсистеме сообщений-подтверждений. То есть каждое большое информационное сообщений сопровождается обратной
5.5. Обмен сообщениями
99
“квитанцией” о доставке. Однако, если квитанция была потеряна в ходе об­ратной доставки, процесс может быть навсегда заблокирован, так как он будет ждать подтверждения, которое он не получит никогда.
Проблема возникает, когда операция приема receive является блоки-
рующей. Выходом из такой ситуации является внедрение еще одного меха­низма, позволяющего проверить получение, но без блокировки отправителя.
Метод адресации. Это другая важная проблема в синхронизации. Она заключается в организации правильной адресации сообщений. Адресация может быть косвенной или прямой. При косвенной адресации, идентифика­ция получателя и отправителя производится в некотором адресном или име­нованном подпространстве (поддомене). Метод ненадежный и зависящий от множества факторов. Чаще всего применяется адресация абсолютная на базе некоторых идентификаторов, которые зачастую делаются уникальными не только в рамках данной системы, но и уникальными вообще. Для генерации подобных идентификаторов существуют отдельные алгоритмы, создающие числовые или символьные последовательности большой длины, зависящие от общего мирового времени и случайных чисел.
Отправитель может указать явно идентификатор получателя, кото­рому ему необходимо доставить сообщение или указать группу идентифи­каторов, например, сгенерированных в определенной последовательности.
В любом случае, почтовый ящик формируется как очередь сообще­ний, которая по своей сути является буфером, рассчитанным на определен­ное число сообщений. Буфер имеет ограничение либо по объему занимае­мой памяти, либо по числу хранимых сообщений. В таком случае, сообще­ния уже могут отправляться не отдельным процессам, а целым почтовым ящикам, из которых они уже могут распределяться по получателям. Это напоминает корпоративную почту предприятия, сообщения которого от­правляются на один и тот же адрес почты, а до адресата доходят в зависи­мости от темы или содержания.
Связь между процессом-получателем и процессом отправителем че­рез почтовый ящик может быть косвенной или прямой, статической или динамической. Статическое связывание выполняется один раз и навсегда при создании ящика для очереди сообщений. Динамическое связывание ис­пользует трансляцию адресом отправителя и получателя и дополнительные операции соединения/разъединения (connect/disconnect).
5. Синхронизация и взаимодействие процессов
100
Кроме того, ящик обычно создается как самостоятельный объект со
своими свойствами и методами. Например, к ящику могут быть применены операции очистки/удаления/создания (clear/create/destroy).
Над почтовыми ящиками могут выполняться следующие простые
операции.
1. Помещение сообщения в почтовый ящик. Положить сообщение
в почтовый ящик может некоторая задача, у которой есть на это право. При этом данная задача может быть блокирована и перемещена в специальную очередь ожидающих отправку задач, если в ящике нет свободного места.
2. Попытка помещения сообщения в почтовый ящик. Задача может
попробовать положить сообщение в почтовый ящик. При этом она полу­чает либо положительный ответ, либо признак того, что место в ящике от­сутствует.
3. Помещение сообщения в начало очереди почтового ящика. Опе-
рация выполняется так же, как и первая, только сообщение помещается в “голову” (т.е. в начало) очереди.
4. Попытка помещения сообщения в начало очереди почтового
ящика. Эквивалентна предыдущей операции “попытка помещения сообще­ния”, только система попробует положить сообщение в начало очереди.
5. Выборка сообщения из почтового ящика. Данная операция вы-
полняется задачей, имеющей право читать сообщение из почтового ящика. При этом задача может быть блокирована и перемещена в очередь задач для ожидания возможности получения сообщения. Это происходит в ос­новном тогда, когда в ящике нет сообщений вообще или в очереди ожида­ющих уже есть другие задачи. Здесь используется механизм взаимного ис­ключения, т.е. пока выполняется операция выборки для одной задачи, все другие ожидающие задачи будут заблокированы.
6. Попытка выборки сообщения из почтового ящика. Действие по-
хоже на предыдущее за исключением того, что задача не блокируется, а про­сто получает признак того, можно ли вернуть сейчас сообщение или нет.
7. Очистка ящика. Операция удаления всех сообщений из очереди
и очистка очереди ожидающих задач (опционально).
Длина сообщения – это третий из рассмотренных выше аспектов
синхронизации сообщениями.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]