Что такое блокировка ядра RTOS и когда вам нужно ее использовать?
Я использую ChibiOS RTOS, и у меня есть некоторые вопросы, которые могут показаться простыми, но от меня это немного ускользает.
ChibiOS имеет функцию под названием:
chSysLock();
а также
chSysUnlock();
Насколько я понимаю, эти две функции будут блокировать и разблокировать ядро соответственно.
Итак, мои вопросы:
- Что делает блокировка ядра?
- Почему вы хотите заблокировать ядро?
И, наконец, давайте использовать этот пример:
static void sem_cb(void) {
chSysLock();
chBSemSignalI(&sem_1);
chSysUnlock();
}
Эта функция просто сигнализирует семафору о том, что его ожидает поток.
Итак, мой последний вопрос:
- Какой смысл блокировать ядро только для того, чтобы подать сигнал семафору? Если я этого не сделаю, ChibiOS будет жаловаться и не будет компилироваться без блокировки системы.
1 ответ
Как правило, при блокировке ядра RTOS планировщик не запускается, поэтому переключение контекста не происходит. Часто некоторые или все прерывания тоже отключены. Блокировка используется для критических разделов - разделов кода, которые должны выполняться без прерывания или прерывания.
Я не эксперт в ChibiOS, но это кажется несколько сложным в этом отношении и не очень подробно задокументировано. Состояния ядра описаны здесь. Имеет два режима блокировки и chSysLock()
вызывает состояние S-Locked, где
"Ядро заблокировано, а обычные источники прерываний отключены. Быстрые источники прерываний включены. В этом состоянии можно вызывать API S-Class и I-Class".
Из документации неясно, означает ли это, что могут использоваться только API класса I/S, или что I/S-mode
API могут быть вызваны только когда заблокированы. Целое государство и его цель не четко определены ИМО. Однако в некоторых ОСРВ обычно есть специальные версии функций, которые не вызывают планировщик, это избавляет обычные функции API от необходимости проверять состояние ядра или контекст прерывания и является незначительной оптимизацией (за счет безопасности в мое мнение). Это подтверждается документацией для chBSemSignalI:
Заметка
Эта функция не перепланируется.
[...]
Функциональный класс:
Это API I-класса, эта функция может вызываться из зоны блокировки системы как потоками, так и обработчиками прерываний.
В вашем примере происходит то, что дан семафор, но планировщик не запустится, поэтому любой ожидающий поток не будет немедленно подготовлен. Не понятно chSysUnlock()
вызывает запуск планировщика - в документации написано "Специальная функция, эта функция предъявляет особые требования, см. примечания", но не дает подсказки относительно того, где можно найти эти примечания.
Я ожидал, что планировщик запустится, и на первый взгляд это функция sem_cb()
казалось бы, служит мало цели; Однако я бы также ожидал chSysLock()/chSysUnlock()
быть вложенным, и в этом случае назначение функции имеет больше смысла. Это позволяет одну семафор-дать функцию (sem_cb()
) использоваться независимо от состояния ядра. То есть безопасно вызывать как в нормальном, так и в S-состоянии, но добавляет издержки, которых должны избегать отдельные API-интерфейсы S-состояния / нормального состояния. Лично я всегда обращался за безопасностью (хотя и не обязательно реализовывал ее таким образом), по крайней мере, до тех пор, пока не было доказано, что накладные расходы неприемлемы. По сути, он гласит: "_дайте семафор, и если ядро не заблокировано, перепланируйте его, иначе отложите перепланирование, пока ядро не будет разблокировано - т.е. после последней вложенной разблокировки".
Это не позволяет однако sem_cb()
вызываться из контекста прерывания, так как это потребует chSysLockFromISR()
,
Вышесказанное делает много предположений из документации и "ожидаемого" поведения ОСРВ. Если бы мне пришлось использовать ChibOS перед лицом такой скудной документации, я бы проверил исходный код, чтобы определить точное поведение.