Квантование времени (time slicing)
Две задачи с одинаковым приоритетом готовы к выполнению. Кто получит процессор и надолго ли? Во FreeRTOS по умолчанию — по очереди, и очередь меняется на каждом прерывании тика. Это и есть квантование времени, и его можно выключить.
Обновлено Редакция GAW
Квантование времени (time slicing) — правило планировщика, по которому задачи одного приоритета сменяют друг друга на каждом прерывании системного тика; время между двумя тиками и есть один квант. Во FreeRTOS это часть политики по умолчанию, которую документация описывает четырьмя словами: вытесняющее планирование с фиксированными приоритетами и круговым (round-robin) квантованием задач равного приоритета.
Четыре слова политики
| Термин | Что означает во FreeRTOS |
|---|---|
| фиксированный приоритет | планировщик не меняет приоритет задачи навсегда, лишь временно поднимает при наследовании против инверсии приоритетов |
| вытесняющий | всегда выполняется самая приоритетная готовая задача; если прерывание сделало готовой более приоритетную, текущая вытесняется посреди кванта |
| round-robin | задачи одного приоритета получают процессор по очереди |
| квантование | очередь сдвигается на каждом тике |
Следствие вытеснения — голодание: задача высокого приоритета, которая никогда не блокируется, навсегда лишает процессора все задачи ниже. Поэтому задачи делают событийными: ждут событие в блокировке, например через уведомление задачи, а не опрашивают флаг в цикле.
Настройка
configUSE_PREEMPTION= 0 выключает вытеснение: переключение происходит только когда задача блокируется, приостанавливается, вызываетtaskYIELD()или его запрашивает прерывание (кооперативное планирование).configUSE_TIME_SLICING= 0 выключает квантование: самая приоритетная задача выполняется по-прежнему, но задачи равного приоритета не сменяются по тику. Если макрос не определён,FreeRTOS.hподставляет 1; шаблонFreeRTOSConfig.hв FreeRTOS-Kernel V11.3.3 ставит 0 сconfigUSE_PREEMPTION= 1.configTICK_RATE_HZзадаёт частоту тика: в шаблоне 100 Гц, в демо-проектах 1000 Гц — по словам документации, выше, чем обычно нужно. Высокая частота повышает разрешение времени, но увеличивает долю процессора, занятую ядром, и укорачивает квант.configIDLE_SHOULD_YIELD= 1 (по умолчанию) заставляет задачу простоя сразу уступать прикладным задачам с приоритетом 0 вместо того, чтобы дорабатывать свой квант.
Само переключение выполняется в прерывании тика; как задачи и обработчики прерываний делят процессор и что это значит для задержки прерываний — в статье «Прерывания и параллельность».
Многоядерные конфигурации
В SMP-режиме FreeRTOS одновременно выполняется по одной задаче на ядро, и допущение «задача низкого приоритета не работает, пока есть готовая высокого» перестаёт быть верным. Для переноса старого кода есть configRUN_MULTIPLE_PRIORITIES = 0 (одновременно работают только задачи одного приоритета) и configUSE_CORE_AFFINITY = 1 с vTaskCoreAffinitySet().
У двухъядерных ESP32 IDF FreeRTOS реализует «best effort round robin»: идеальная очередь невозможна, потому что задача может быть закреплена за другим ядром, поэтому выбранная задача просто переставляется в конец списка. Каждое ядро получает собственный тик того же периода (возможно, со сдвигом фазы), но счёт времени ведёт только ядро 0; ядро 1 лишь проверяет, не пора ли переключить задачу, и вызывает хук тика. Закрепите все задачи одного приоритета за одним ядром — и квантование станет точным; в режиме CONFIG_FREERTOS_UNICORE восстанавливается алгоритм обычного FreeRTOS.
Частые вопросы
Что произойдёт, если выключить configUSE_TIME_SLICING?
Планировщик по-прежнему всегда выполняет самую приоритетную готовую задачу, но перестаёт переключать задачи одного приоритета только потому, что пришёл тик. Переключение между ними произойдёт, когда текущая задача заблокируется, приостановится или сама уступит процессор через taskYIELD(). По умолчанию (если макрос не определён) FreeRTOS.h ставит 1, а шаблон FreeRTOSConfig.h из FreeRTOS-Kernel V11.3.3 — 0.
Какую частоту тика выбрать?
Шаблон конфигурации задаёт 100 Гц, демо-проекты FreeRTOS — 1000 Гц, и документация прямо называет 1000 Гц значением выше обычно необходимого: это режим для тестирования ядра. Чем выше частота, тем точнее измеряется время и короче квант, но тем большую долю процессора забирает само ядро. Время между двумя тиками — это и есть один квант при квантовании времени.
Почему во FreeRTOS на ESP32 round-robin «негарантированный»?
Потому что у IDF FreeRTOS два ядра, каждое выбирает задачу само, а задача может быть закреплена за другим ядром. Планировщик реализует «best effort round robin»: выбранную задачу переставляет в конец списка, чтобы на следующем тике или yield шанс получили остальные. Если все задачи одного приоритета закреплены за одним ядром, квантование получается идеальным; в одноядерном режиме CONFIG_FREERTOS_UNICORE восстанавливается алгоритм обычного FreeRTOS.
Источники
- FreeRTOS. FreeRTOS Kernel documentation: Task scheduling — single-core, AMP and SMP (Kernel features), 2026 — разд. Default scheduling policy: по умолчанию — вытесняющее планирование с фиксированными приоритетами и круговым квантованием времени между задачами одного приоритета; «фиксированный» — планировщик не меняет приоритет задачи навсегда, но может временно поднять его при наследовании приоритета; «вытесняющий» — всегда выполняется самая приоритетная готовая задача, даже если ISR сделала её готовой посреди кванта; «round-robin» — задачи одного приоритета получают процессор по очереди; «time sliced» — переключение на каждом прерывании тика, время между тиками — один квант; разд. Avoiding starvation: задача высокого приоритета, которая никогда не блокируется, навсегда лишает времени все задачи ниже, поэтому задачи делают событийными; разд. Configuring: configUSE_PREEMPTION = 0 — переключение только при блокировке или приостановке, вызове taskYIELD() или по запросу из ISR; configUSE_TIME_SLICING = 0 — планировщик не переключает задачи равного приоритета по тику; разд. SMP: configRUN_MULTIPLE_PRIORITIES = 0 — одновременно выполняются только задачи одного приоритета, configUSE_CORE_AFFINITY = 1 — vTaskCoreAffinitySet() закрепляет задачу за ядрами
- FreeRTOS. FreeRTOS-Kernel V11.3.3: examples/template_configuration/FreeRTOSConfig.h и include/FreeRTOS.h; страница Customisation (FreeRTOSConfig.h) — шаблон: configTICK_RATE_HZ 100 — частота прерывания тика, обычно выводится из configCPU_CLOCK_HZ; configUSE_PREEMPTION 1; configUSE_TIME_SLICING 0 с комментарием: 1 — переключать готовые задачи равного приоритета на каждом тике, 0 — не переключать только из-за тика; configIDLE_SHOULD_YIELD 1; FreeRTOS.h: configUSE_TIME_SLICING равно 1, если не определено; страница Customisation: демо-приложения используют тик 1000 Гц — выше, чем обычно нужно; высокая частота тика повышает разрешение времени, но увеличивает долю процессора, занятую ядром, и уменьшает квант каждой задачи
- Espressif. ESP-IDF Programming Guide v6.1, ESP32: FreeRTOS (IDF), разд. Scheduling — разд. Time Slicing: в IDF FreeRTOS идеальный round-robin невозможен, потому что задача может быть не способна выполняться на данном ядре; реализован «best effort round robin» — выбранная задача ставится в конец списка; идеальное квантование — если все задачи данного приоритета закреплены за одним ядром; разд. Tick Interrupts: каждое ядро получает свой периодический тик, тики одного периода, но могут быть сдвинуты по фазе; Core 0 единолично ведёт счёт времени, Core 1 только проверяет необходимость квантования и вызывает хук тика; разд. Single-Core Mode: при CONFIG_FREERTOS_UNICORE восстанавливается алгоритм Vanilla FreeRTOS, включая идеальный round-robin
Нашли ошибку? ·
Смотрите также
- SysTick24-битный таймер ядра Cortex-M для системного тика
- Задача простоя (idle task)Задача FreeRTOS с наименьшим приоритетом: работает, когда больше некому, чистит память удалённых задач и вызывает хук простоя
- Инверсия приоритетовЗадача с высоким приоритетом ждёт задачу с низким из-за общего ресурса
- Уведомление задачи (task notification)Событие FreeRTOS, отправляемое прямо задаче: быстрее и экономнее семафора, но получатель только один
- Задержка прерыванияВремя от запроса до обработчика: Cortex-M3 и AVR
- Прерывания и общие данныеISR на AVR и Cortex-M, атомарность, критические секции, кольцевой буфер
- ESP32ESP32, S2, S3, C2, C3, C5, C6, H2, P4: ядра, радио, USB, GPIO — сравнение и выбор