Ядро реального времени не делает систему быстрее. Оно меняет правила планирования так, чтобы важная задача получала процессор за предсказуемое время, а не «в среднем быстро». Для аудио, промышленных контроллеров, робототехники и измерительных стендов важна не пропускная способность, а худшая задержка — jitter. PREEMPT_RT много лет жил отдельным патчем, а начиная с версии 6.12 вошёл в основной код. Разберём, как его проверить, собрать и измерить, не превращая рабочий ноутбук в нестабильный стенд.
Что такое реальное время
Обычный планировщик распределяет процессор справедливо и держит высокую пропускную способность. Если драйвер занял ядро на несколько миллисекунд, приложение подождёт. Для веб-сервера это нормально, для станка с импульсом каждые 500 микросекунд — брак или авария.
Жёсткое реальное время означает гарантию худшего отклика. Мягкое допускает редкие опоздания. Linux с PREEMPT_RT относят к мягкому и почти жёсткому реальному времени: он предсказуем на исправном оборудовании, но не заменяет специализированный контроллер там, где нужна гарантия производителя.
Что меняет PREEMPT_RT
Патч делает почти весь код ядра вытесняемым. Обработчики прерываний переводятся в потоки, которые планировщик может приостановить. Спинлоки получают наследование приоритета, чтобы низкоприоритетная задача не блокировала высокоприоритетную. Таймеры работают с высоким разрешением, критические секции сокращены.
Плата — меньшая пропускная способность и расход на переключения. Поэтому RT-ядро ставят не «для скорости», а когда важна предсказуемость. Сервер баз данных от такой замены, скорее всего, потеряет производительность.
Как проверить, что ядро уже RT
Начните с фактов. В RT-ядре существует файл /sys/kernel/realtime, а в конфигурации включён CONFIG_PREEMPT_RT:
uname -v
cat /sys/kernel/realtime
grep -E '^CONFIG_PREEMPT_RT=' /boot/config-$(uname -r)
Если файл отсутствует или команда возвращает ошибку, перед вами обычное ядро. Строка PREEMPT_RT в uname -v тоже встречается у сборок с патчем, но полагаться только на неё не стоит.
Готовое ядро или своя сборка
В Debian и производных есть пакет linux-image-rt-amd64. В Fedora и RHEL — kernel-rt, который ставится рядом с обычным и появляется отдельным пунктом в GRUB. В Ubuntu вариант зависит от выпуска и подписки, поэтому сначала поищите пакет:
apt search linux-image-rt
sudo apt install linux-image-rt-amd64 rt-tests
sudo dnf install kernel-rt rt-tests
После установки перезагрузитесь и выберите RT-ядро. Не удаляйте обычное: оно понадобится, если RT-сборка не подхватит драйвер.
Своя сборка нужна для нестандартных драйверов или патчей. В make menuconfig выберите Processor type and features → Preemption Model → Fully Preemptible Kernel (Real-Time), поднимите частоту таймера до 1000 Гц и отключите тяжёлую отладку:
sudo apt build-dep linux
make olddefconfig
make menuconfig
make -j"$(nproc)" bindeb-pkg
Готовые .deb появятся уровнем выше каталога сборки. Установите образ и заголовки, обновите GRUB и только после успешной загрузки удаляйте старое ядро.
Настройка оборудования и параметров загрузки
Предсказуемость начинается с прошивки. В BIOS отключите энергосберегающие C-states, Turbo Boost и агрессивное управление частотой, если они дают скачки. Для стенда также отключают SMT и лишние устройства, но для рабочей станции это компромисс.
В командную строку ядра добавляют изоляцию процессоров и отключение частотного драйвера. Пример для машины, где задачи реального времени живут на ядрах 2 и 3:
isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 intel_pstate=disable processor.max_cstate=1
isolcpus убирает ядра из общего планировщика, nohz_full снижает число тиков, rcu_nocbs выносит callback-и RCU, irqaffinity оставляет прерывания на ядрах 0 и 1. На AMD вместо intel_pstate используют amd_pstate=disable. Параметр idle=poll уменьшает задержку, но резко повышает нагрев — на ноутбуке он неуместен.
Изоляция, приоритеты и прерывания
Одной строки загрузки мало. Приложение должно попросить RT-приоритет и заблокировать память, иначе страничные отказы добавят паузы:
ulimit -l unlimited
taskset -c 2 chrt -f 80 ./controller
ps -eo pid,cls,rtprio,comm | awk '$2=="FF"'
Класс FF означает FIFO с фиксированным приоритетом. Не ставьте приложению приоритет 99: на этом уровне работают критичные потоки ядра. В RT-ядре обработчики прерываний уже существуют как потоки, их приоритет можно поднять точечно:
pgrep -af 'irq/.*xhci'
sudo chrt -f -p 90 $(pgrep -f 'irq/.*xhci' | head -1)
Для контейнеров и сервисов вместо isolcpus удобнее cgroup v2 с cpuset.cpus: isolcpus работает, но не управляет дочерними процессами так гибко.
Измерение задержек
Главный инструмент — cyclictest из пакета rt-tests. Он измеряет время между запланированным и фактическим пробуждением потока. Запускайте его на изолированном ядре, с блокировкой памяти и реалистичной нагрузкой:
sudo cyclictest -m -S -p90 -i200 -h400 -a2 -t1 -D 10m
-m блокирует память, -p90 задаёт приоритет, -i200 — интервал в микросекундах, -h400 строит гистограмму, -a2 привязывает поток к ядру 2, -D 10m ограничивает тест десятью минутами. Смотрите не на среднее, а на максимум. Повторите тест под нагрузкой:
stress-ng --cpu 2 --io 2 --vm 1 --timeout 10m
sudo hwlatdetect --duration=60
hwlatdetect ищет паузы от прошивки и системного управления, прежде всего SMI. Если он показывает всплески, программная настройка не поможет: проблема в BIOS, виртуализации или оборудовании.
Типичные ошибки
- Ставить RT-ядро на сервер ради «производительности».
- Забывать про
mlockallи получать задержки на страничных отказах. - Отключать RT-throttling и позволять одному потоку занять процессор навсегда.
- Оставлять отладочные опции ядра и удивляться высокому максимуму.
- Тестировать в графической сессии с браузером, а потом винить ядро.
Порог sched_rt_runtime_us по умолчанию оставляет RT-задачам 95% времени. Менять его стоит осознанно и с работающим watchdog. Обычно достаточно изоляции и приоритетов.
Чек-лист
- Проверьте
/sys/kernel/realtimeи конфигурацию. - Оставьте обычное ядро в загрузчике.
- Отключите мешающие C-states и Turbo в BIOS.
- Изолируйте ядра и привяжите прерывания к остальным.
- Измерьте максимум
cyclictestпод нагрузкой.
Итог
PREEMPT_RT — инструмент предсказуемости, а не ускорения. В свежих ядрах он доступен без отдельного патча, но требует дисциплины: подходящего оборудования, изоляции процессоров, приоритетов и честных измерений. Начните с готового пакета, снимите baseline через cyclictest, затем меняйте по одной настройке и сравнивайте максимум задержки. Такой подход даёт повторяемый результат вместо веры в волшебную строку загрузчика.