Лабораторное занятие №2.
Работа с очередями в ОСРВ «FreeRTOS»
Необходимость использования очередей. Характеристики очередей: хранение информации в очереди, доступ из множества задач, блокировка при чтении из очереди, блокировка при записи в очередь. Работа с очередями: создание очереди, запись элемента в очередь, чтение элемента из очереди, удаление очереди. Применение очередей при работе с UART.
Самый простой способ организовать обмен информацией между задачами — использовать общую глобальную переменную. Доступ к такой переменной осуществляется одновременно из нескольких задач. Однако такой подход имеет существенный недостаток: при совместном доступе нескольких задач к общей переменной возникает ситуация, когда выполнение одной задачи прерывается планировщиком именно в момент модификации общей переменной, когда та содержит не окончательное (искаженное) значение. При этом результат работы другой задачи, которая получит управление и обратится к этой переменной, также окажется искаженным.
Решить подобные проблемы позволяет использование очередей для передачи информации между задачами. Во FreeRTOS очереди представляют собой фундаментальный механизм взаимодействия задач друг с другом. Они могут быть использованы для передачи информации как между задачами, так и между прерываниями и задачами. Основное преимущество использования очередей —это то, что их использование является безопасным в многозадачной среде (thread safe).
То есть при использовании очередей автоматически решается проблема совместного доступа нескольких задач к одному аппаратному ресурсу, роль которого в данном случае играет память.
|
Хранение информации в очереди
Информация хранится в очереди в виде элементов (items) — блоков памяти фиксированного размера. В качестве элемента очереди может выступать любая переменная языка Си. В случае если это переменная типа char, размер блока будет равен 1 байту, если это структура или массив, размер блока будет равен, соответственно, размеру структуры или массива.
Элементы очереди в контексте обмена информацией между задачами будем называть сообщениями.
Запись элемента в очередь приводит к созданию побайтовой копии элемента в очереди. Побайтовое копирование происходит и при чтении элемента из очереди.
Очередь может хранить в себе конечное число элементов фиксированного размера. Максимальное число элементов, которое может хранить очередь, называется размером очереди. Как размер элемента, так и размер очереди задаются при создании очереди и остаются неизменными до ее удаления. Важно отметить, что память выделяется сразу под все элементы очереди, то есть пустая и заполненная очередь не отличаются друг от друга по объему занимаемой памяти.
При записи элементов в очередь динамического выделения памяти не происходит. Очередь функционирует по принципу «первым вошел — первым вышел» (First In First Out, FIFO), то есть элемент, который раньше остальных был помещен в очередь (в конец очереди), будет и прочитан раньше остальных (рис. 1). Обычно элементы записываются в конец («хвост») очереди и считываются с начала («головы») очереди.
Рисунок 1 Механизм обмена данными через очередь между двумя задачами
Доступ из множества задач
|
Очередь — это самостоятельный объект ядра, она не принадлежит ни одной конкретной задаче. Напротив, любое количество задач могут как читать, так и записывать данные в одну и ту же очередь. Следует отметить, что ситуация, когда в очередь помещают данные сразу несколько задач, является «обычным делом» для программ под управлением ОСРВ, однако чтение данных несколькими задачами из одной очереди встречается редко.
Блокировка при чтении из очереди
Когда задача пытается прочитать данные из очереди, которая не содержит ни одного элемента, то задача переходит в блокированное состояние. Такая задача вернется в состояние готовности к выполнению, если другая задача (или прерывание) поместит данные в очередь.
Выход из блокированного состояния возможен также при истечении тайм-аута, если очередь на протяжении этого времени оставалась пуста.
Данные из очереди могут читать сразу несколько задач. Когда очередь пуста, то все они находятся в блокированном состоянии. Когда в очереди появляется элемент данных, начнет выполняться та задача, которая имеет наибольший приоритет.
Возможна ситуация, когда равноприоритетные задачи ожидают появления данных в очереди. В этом случае при поступлении данных в очередь управление получит та задача, время ожидания которой было наибольшим. Остальные же останутся в блокированном состоянии.