На связи Ионенко Евгений, в октябре 2025 года в Нижнем Новгороде на форуме «Промышленная автоматизация: переход на открытую АСУ ТП» с коллегами зашел интересный разговор о Linux с патчем реального времени. В разговоре затронули разные интересные моменты: работа через гипервизоры, выделения ядер и отличия от QNX. Поговорили и о том, когда у наших вендоров появятся решения под такие задачи для встроенных систем. Успокоил коллег, что разработчики операционных систем на базе Linux отслеживают и видят все запросы сообщества, но как обычно бывает, объем задач превышает возможности команды.

Договорились о том, что я напишу небольшой гайд, рассказывающий что и как можно сделать, чтобы оптимизировать время отклика. Отдельно отмечу, что задачу доказать, что Linux с патчем PREEMPT_RT является операционной системой жёсткого реального времени перед собой не ставлю. На мой взгляд, она такой не является, так сказать by designe, в отличие от тех же QNX, VxWorks и ThreadX.

Рассказ построю на примере одноплатника repka‑pi 3 ver. 1.6, так как на нем я периодически тестирую софт.

1) Установка ядра с патчем PREEMPT_RT.

Разработчиками уже предусмотрено ядро с патчем PREEMPT_RT, за что им большое спасибо. Выбираем это ядро через утилиту repka‑config.

выбор ядра Linux
выбор ядра Linux

Ждем установки и перезагружаемся. После этого проверяем, что все установилось и запустилось командой uname ‑a. И проверяем, что ядро теперь 6.1.11-rt7.

2) Удаление лишних приложений и сервисов.

Тут все очевидно и понятно, чем меньше приложений конкурируют за процессорное время, тем лучше. Тот же GUI можно смело отключать.

3) Выбор политики планирования.

Установленный патч PREEMPT_RT не говорит о том, что нужное нам приложение запускается в политике планирования для реального времени, так как его запускает планировщик по умолчанию — CFS (Completely Fair Scheduler). Он разработан таким образом, чтобы обеспечить справедливое процессорное время для всех процессов и использует структуру данных «красно‑черное дерево» для отслеживания процессов и их ЦПУ‑времени. Планировщик CFS назначает процессорное время процессам в зависимости от их веса и количества использованного ими процессорного времени.

Доступные политики планирования для реального времени в ОС Linux:

  • FIFO — First In, First Out Scheduling. Это простой планировщик в порядке очереди, который дает наивысший приоритет для задачи с наивысшим уровнем приоритета. FIFO планировщик используется для того, чтобы задачи реального времени получали процессорное время, которое они используют без прерывания более низкоприоритетными задачами. В данной политике задача получает уровень приоритета от 1 до 99, где 1 — самый низкий приоритет, а 99 является наивысшим приоритетом. 

    Чтобы запустить приложение с использованием такого планировщика, используется команда:

    chrt --fifo 80 ./имя_приложения
    где 80 - это приоритет.

    Для просмотра приложений, которые запущены в планировщике FIFO можно использовать следующую команду:

    ps -eLo rtprio,cls,pid,pri,nice,cmd | grep "FF" | sort -r
  • RR — Round Robin. Этот планировщик с циклическим перебором используется для обеспечения получения задачами реального времени необходимого времени ЦПУ, без ущемления задач с более низким приоритетом временем ЦПУ. Основанный на циклическом планировании алгоритм, назначает фиксированное время каждой задаче в циклической очереди. Когда это время истекает, задача перемещается в конец очереди и следующая задача, запланированная для выполнения получает свое время для выполнения, независимо от того, завершено выполнение предыдущей задачи или нет. Это гарантирует, что все задачи получают справедливую долю процессорного времени, и что ни одна задача не осталась без выделенного времени. В данной политике задачи получают уровень приоритета от 1 до 99, где 1 — самый низкий приоритет, а 99 является наивысшим приоритетом.

    Чтобы запустить приложение с использованием такого планировщика, используется команда:

    chrt --RR 80 ./имя_приложения
    где 80 - это приоритет.

    Для просмотра приложений, которые запущены в планировщике RR можно использовать следующую команду:

    ps -eLo rtprio,cls,pid,pri,nice,cmd | grep "RR" | sort -r
  • EDF — Early Deadline First (deadline). Он использует алгоритм планирования, основанный на сроках, чтобы гарантировать, что процессы укладываются в установленные сроки. Планировщик дедлайнов оптимизирован для приложения реального времени, которым требуется гарантированное процессорное время. Политика планирования сроков реализуется с помощью алгоритма GEDF (Global Early Deadline First), который присваивает Процессорное время для процессов в зависимости от их дедлайнов. Алгоритм GEDF гарантирует, что процессы укладываются в установленные сроки, планируя их выполнение в ЦПУ как можно раньше.

    Разовая задача включает в себя серию заданий, каждое из которых активируется не чаще одного раза за период. Каждому заданию назначается относительный срок (relative deadline), указывающий, когда оно должно завершиться, и время вычислений (computation time), представляющее время процессора, необходимое для его выполнения. Момент, в который задача становится готовой к выполнению из‑за нового задания, требующего выполнения, называется временем поступления (arrival time). Время начала (start time) означает, что задача начинает выполняться. Следовательно, абсолютный крайний срок (absolute deadline) определяется путем добавления относительного крайнего срока ко времени прибытия.

    Early Deadline First
    Early Deadline First

    При настройке треда с помощью системного вызова sched_setattr можно задать три параметра: время выполнения (Runtime), крайний срок (Deadline) и период (Period).

    Эти настройки могут не всегда соответствовать условиям, упомянутым ранее: обычно время выполнения устанавливается выше среднего времени обработки (или наихудшего времени выполнения), крайний срок совпадает с относительным крайним сроком, а период соответствует продолжительности задачи.

    Для запуска приложения с использованием такого планировщика, используется команда:

    chrt -d -T <runtime> -D <deadline> -P <period> <command> <command options>

    Где:

  • Runtime: Время выполнения, отведенное задаче.

  • Deadline: Через какое время после начала периода должна быть запущена и выполнена задача.

  • Period: Через какое время будет повторное выполнение.

    Все значения в наносекундах.

    Должно соблюдаться правило: RUNTIME <= DEADLINE <= PERIOD.

    Пропуск любого из параметров приведет к следующему:

  • Пропуск значения времени Runtime приведет к тому, что время Runtime будет установлено на значение Deadline.

  • Пропуск значения времени Deadline приведет к тому, что Deadline будет установлен на значение Period.

  • Пропуск значения времени Period приведет к тому, что Period будет установлен на значение Deadline.

    Пример строки запуска приложения:

    chrt -d --sched-runtime 1000000 --sched-deadline 5000000 --sched-period 5000000 ./имя_приложения

    Для просмотра приложений, которые запушены в планировщике EDF (deadline) можно использовать следующую команду:

    ps -eLo rtprio,cls,pid,pri,nice,cmd | grep "DL" | sort -r

Отдельно стоит отметить, что в операционной системе живут приложения, запущенные на исполнение с разными политиками планирования, и среди этих политик планирования есть свои приоритеты:

  1. EDF - Первый приоритет.

  2. FIFO/RR -  Второй приоритет.

  3. CFS - Третий приоритет.

Например, задача с приоритетом 99, спланированная через FIFO или RR, не прервет выполняющуюся задачу, запущенную через планировщик EDF. Ее способна прервать только задача, спланированная через EDF и имеющая более ближнее время дедлайна. Также стоит аккуратно использовать приоритеты выше 90, так как это может привести к конфликтам с процессами ОС.

Перед запуском нужного приложения следует настроить ограничения для пользователя в файл limits.conf:

sudo nano /etc/security/limits.conf 

Добавим туда две строчки:

Сохраняем файл и на всякий случай перезагрузим ОС или перезайдем в нее и запускаем нужное приложение в нужном планировщике.

требуемое_имя_пользователя - rtprio 99
требуемое_имя_пользователя - memlock unlimited #Нет ограничений на блокировку памяти

4) Отключение CPU frequence scaling.

Частота ЦПУ может менять в процессе работы, что меняет аппаратную производительность.

CPU frequence scaling
CPU frequence scaling

Для этого нужно установить пакет cpufrequtils. Делаем это командой:

sudo apt install cpufrequtils 

Отредактируем конфигурационный файл cpufrequtils

ENABLE="true"
GOVERNOR="schedutil"  # или /ondemand/сonservative/performance/powersave
MAX_SPEED="648000"    # 648 MHz / или свое значение 
MIN_SPEED="648000"    # 648 MHz / или свое значение 

Доступные варианты GOVERNOR:

  • Performance — фиксирует частоту на максимально разрешённой

  • Powersave — фиксирует минимальную частоту

  • Ondemand — динамически повышает частоту при нагрузке (баланс между производительностью и энергопотреблением) в пределах доступного диапазона

  • Conservative — аналогичен ondemand, но изменяет частоты более плавно, избегая резких скачков

  • Schedutil — современный алгоритм, использующий данные планировщика задач Linux для оптимизации частоты

После сохранения файла перезагружаем ОС и проверяем, что все работает как нужно.

5) Изолирование ядер ЦПУ

Для этого запускаем исполнение приложения через taskset:

taskset -c 0,1 ./имя_приложения

Исполнение будет на ядрах 0 и 1.

Важно отметить, что при назначении через  taskset, операционная система может повесить еще что-то на эти ядра . 

Для того, чтобы этого не происходило, нужно изменять параметры загрузки ядра.

6) Установить приоритет для операций ввода-вывода

ionice -c1 -n0 ./имя_приложения

c1 - класс реального времени.

n0 - приоритет планирования ввода-вывода. От 0 до 7, где 0 - максимальный.

Итоговая строка запуска приложения выглядит так:

 taskset -c 0,1 ionice -c1 -n0 chrt --RR 90 ./имя_приложения 

Все, что описано выше — это краткий перечень того, что можно сделать обычному пользователю для решения своих задач. 

При этом важно понимать, что для разработки системы реального времени важны все ее компоненты и взаимодействие между ними. Просто использование RTOS (real‑time operating system) не является волшебной палочкой, ее нужно использовать правильно и учитывать ее возможности и ограничения в разрабатываемом программном обеспечении для этой ОС.

P. S. Отдельная благодарность Константину, чьи комментарии и критика позволили написать статью понятным языком и разобраться в отдельных аспектах работы планировщиков.

Комментарии (0)