Компоненты и технологии • №2 '2011 компоненты


xSemaphoreGiveRecursive()



Pdf көрінісі
бет87/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   83   84   85   86   87   88   89   90   ...   129
Kurniz

xSemaphoreGiveRecursive().
рис. 2. Результат работы учебной программы № 1 без использования мьютекса
рис. 3. Результат работы учебной программы № 1 с применением мьютекса


137
КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 8 '2011
www.kite.ru
компоненты
микроконтроллеры
Для того чтобы использовать рекурсивные мьютексы в про-
грамме, необходимо установить макроопределение configUSE_
RECURSIVE_MUTEXES в файле FreeRTOSConfig.h равным «1».
Как и обращение к обычному мьютексу, обращение к рекурсивно-
му мьютексу осуществляется с помощью дескриптора (идентифика-
тора) мьютекса — переменной типа xSemaphoreHandle.
API-функции для работы с рекурсивными мьютексами:
xSemaphoreCreateRecursiveMutex()

— создание рекурсивного мью-
текса;
xSemaphoreTakeRecursive()

захват рекурсивного мьютекса;
xSemaphoreGiveRecursive()

— освобождение (возврат) рекурсив-
ного мьютекса.
Набор параметров и возвращаемое значение этих API-функций 
ничем не отличаются от соответствующих API-функций для рабо-
ты с обычными мьютексами. Стоит помнить лишь о том, что API-
функции для работы с рекурсивными мьютексами нельзя применять 
к обычным мьютексам и наоборот.
Проблемы при использовании мьютексов
Инверсия приоритетов
Вернемся к рассмотрению учебной программы № 1. Возможная 
последовательность выполнения задач приведена на рис. 4. Такая 
последовательность имела бы место, если во FreeRTOS не был бы 
реализован механизм наследования приоритетов, о котором будет 
рассказано ниже.
Пусть в момент времени (1) низкоприоритетная задача 1 вытес-
нила задачу Бездействие, так как закончился период пребывания 
задачи 1 в блокированном состоянии (рис. 4). Задача 1 захватывает 
мьютекс (становится его владельцем) и начинает посимвольно вы-
водить свою строку на дисплей (2). В момент времени (3) разбло-
кируется высокоприоритетная задача 2, при этом она вытесняет 
задачу 1, когда та еще не закончила вывод строки на дисплей. Задача 
2 пытается захватить мьютекс, однако он уже захвачен задачей 1, 
поэтому задача 2 блокируется в ожидании, когда мьютекс станет 
доступен. Управление снова получает задача 1, она завершает вы-
вод строки на дисплей — операция с ресурсом завершена. Задача 
1 возвращает мьютекс обратно — мьютекс становится доступен 
(момент времени (4)). Как только мьютекс становится доступен, 
разблокируется задача 2, которая ожидала его освобождения. Задача 
2 захватывает мьютекс (становится его владельцем) и выводит свою 
строку на дисплей. Приоритет задачи 2 выше, чем у задачи 1, поэто-
му задача 2 выполняется все время, пока полностью не выведет 
свою строку на дисплей, после чего она отдает мьютекс обратно 
и блокируется на заданное API-функцией vTaskDelay() время — мо-
мент времени (5). Задача 1 снова получает управление, но на непро-
должительное время — пока также не перейдет в блокированное 
состояние, вызвав vTaskDelay().
Учебная программа № 1 и рис. 4 демонстрируют одну из возмож-
ных проблем, возникающих при использовании мьютексов для реа-
лизации механизма взаимного исключения, — проблему инверсии 
приоритетов (Priority Inversion) [7]. На рис. 4 представлена ситуация, 
когда высокоприоритетная задача 2 вынуждена ожидать, пока низ-
коприоритетная задача 1 завершит действия с ресурсом и возвратит 
мьютекс обратно. То есть на некоторое время фактический приори-
тет задачи 2 оказывается ниже приоритета задачи 1: происходит ин-
версия приоритетов.
В реальных программах инверсия приоритетов может оказывать 
еще более негативное влияние на выполнение высокоприоритетных 
задач. Рассмотрим пример. В программе могут существовать также 
задачи со «средним» приоритетом — ниже, чем у высокоприоритет-
ной, которая ожидает освобождения мьютекса, но выше, чем у низ-
коприоритетной, которая в данный момент захватила мьютекс и вы-
полняет действия с разделяемым ресурсом. Среднеприоритетные 
задачи могут разблокироваться на протяжении интервала, когда низ-
коприоритетная задача владеет мьютексом. Такой сценарий является 
наихудшим, так как ко времени, когда высокоприоритетная задача 
ожидает освобождения мьютекса, будет добавлено время выполне-
ния среднеприоритетных задач (рис. 5).
Низкоприоритетная задача стала владельцем мьютекса ранее. 
Происходит некоторое событие, за обработку которого отвечает высо-
коприоритетная задача. Она разблокируется и пытается захватить мью-
текс (1), это ей не удается, и она блокируется — момент времени (2) 
на рис. 5. Управление снова возвращается низкоприоритетной задаче, 
которая в момент времени (3) вытесняется задачей, приоритет кото-
рой выше (среднеприоритетной задачей). Среднеприоритетная задача 
может выполняться продолжительное время, в течение которого вы-
сокоприоритетная будет ожидать, пока мьютекс не будет освобожден 
низкоприоритетной задачей (4). Время реакции на событие при этом 
значительно удлиняется — величина dT на рис. 5.
В итоге инверсия приоритетов может значительно ухудшить время 
реакции микроконтроллерной системы на внешние события.
Для уменьшения (но не полного исключения) негативного влияния 
инверсии приоритетов во FreeRTOS реализован механизм наследова-
ния приоритетов (Priority Inheritance). Его работа заключается во вре-
менном увеличении приоритета низкоприоритетной задачи-владельца 
мьютекса до уровня приоритета высокоприоритетной задачи, которая 
в данный момент пытается захватить мьютекс. Когда низкоприори-
тетная задача освобождает мьютекс, ее приоритет уменьшается до зна-
чения, которое было до повышения. Говорят, что низкоприоритетная 
задача наследует приоритет высокоприоритетной задачи.
Рассмотрим работу механизма наследования приоритетов на примере 
программы с высоко-, средне- и низкоприоритетной задачами (рис. 6).


Достарыңызбен бөлісу:
1   ...   83   84   85   86   87   88   89   90   ...   129




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет