Семафор - это объект RTOS, предназначенный для синхронизации задач и обеспечения конкурентного доступа к ресурсам программы. В текущий момент времени только одна задача может "владеть" семафором. Задача, пытающаяся завладеть уже захваченным семафором переводится в состояние WAITING
и ставится в очередь задач, ожидающих семафор, до тех пор пока он не будет освобожден.
Существует несколько типов семафоров - счетный семафор, двоичный семафор (подтип счетного) и семафор конкурентного доступа или мютекс. В TNKernel мютекс является отдельным объектом и рассмотрен в соответствующем разделе.
Счетный семафор можно сравнить с менеджером отеля у которого есть несколько ключей от одной комнаты. Менеджер будет выдавать жильцам комнаты (задачам RTOS) ключи до тех пор, пока они не кончатся (семафор захвачен). Как только один из жильцов вернет ключ от комнаты, он сразу будет выдан жильцу (задаче), ожидающему ключ.
Таким образом со счетным семафором ассоциировано такое понятие как счетчик свободных ресурсов. Если счетчик больше нуля - семафор может быть захвачен одной из задач, при этом счетчик ресурсов уменьшается на единицу. Если счетчик равен нулю - семафор заблокирован, и все задачи пытающиеся его захватить будут поставлены в очередь ожидания семафора. Как только счетчик ресурсов семафора станет больше нуля - семафор захватит первая задача из очереди ожидающих.
Двоичный семафор является подтипом счетного - его счетчик свободных ресурсов может принимать только значения 0 (захвачен) и 1 (свободен). В TNKernel семафоры не разделяются на двоичные и счетные - максимальное значение счетчика ресурсов задается при создании семафора.
Каждый семафор ассоциируется со структурой управления:
typedef struct TN_SEM_S_STRUCT { CDLL_QUEUE_S wait_queue; TN_UWORD count; TN_UWORD max_count; TN_OBJ_ID id_sem; } TN_SEM_S;
В состав структуры семафора входят следующие элементы:
wait_queue |
Очередь задач, ожидающих освобождения семафора |
count |
Счетчик свободных ресурсов семафора |
max_count |
Максимальное значение счетчика свободных ресурсов |
id_sem |
Поле идентификации объекта как семафора |
TN_DEBUG
. Тем не менее, прямой доступ к элементам структуры семафора крайне не рекомендуется, так как это является вмешательством в работу планировщика и других сервисов RTOS.
TNKernel имеет следующий набор функций (сервисов) для управления семафорами:
Сервис | Описание | Свойства |
---|---|---|
Создание и удаление семафора | ||
tn_sem_create() | Создание семафора | |
tn_sem_delete() | Удаление семафора | |
Освобождение семафора | ||
tn_sem_signal() | Освобождение семафора | |
tn_sem_isignal() | Освобождение семафора в прерывании | |
Захват семафора | ||
tn_sem_acquire() | Захват семафора | |
tn_sem_polling() | Попытка захвата семафора без блокировки задачи | |
tn_sem_ipolling() | Попытка захвата семафора в прерывании |