Операционные системы
Теория: Планировщик и приоритеты
Процессор не выполняет все процессы одновременно, хотя со стороны кажется, что сервер «работает со всем сразу».
На самом деле операционная система постоянно решает, какому процессу дать процессор прямо сейчас. Этим занимается планировщик (scheduler).
Планировщик управляет очередью процессов, оценивает их состояние и распределяет время выполнения так, чтобы система оставалась отзывчивой, а ресурсы — использовались эффективно. Каждый процесс находится в одном из состояний:
В Linux можно увидеть, в каком состоянии находится каждый процесс.
Команда выведет список процессов с их флагами. Основные состояния такие:
- R (running) — процесс выполняется прямо сейчас или готов к выполнению;
- S (sleeping) — процесс временно спит, ожидая событие, например ввод-вывод;
- D (uninterruptible sleep) — ожидает системный ресурс и не может быть прерван;
- T (stopped) — остановлен сигналом или отладчиком;
- Z (zombie) — завершён, но родитель ещё не забрал код выхода.
Эти флаги можно наблюдать и в top, где колонка STAT показывает текущее состояние. Если большинство процессов находятся в S — система загружена ожиданием, но не процессором. Если много R — CPU активно занят вычислениями.
Планировщик работает только с теми, кто готов к запуску, и выделяет им квант времени — короткий интервал, в течение которого процесс использует CPU. Когда квант заканчивается, процесс приостанавливается, и процессор передаётся следующему. Быстрая смена задач — десятки и сотни раз в секунду — создаёт иллюзию параллельной работы даже на одноядерных системах.
Если процесс ждёт данных, планировщик временно убирает его из очереди, чтобы не тратить CPU впустую. Когда операция завершена, процесс возвращается обратно. Так достигается баланс между скоростью отклика и эффективностью использования ресурсов — ключевой принцип стабильной работы серверов.
Приоритеты и параметр nice
Главный инструмент влияния на поведение планировщика — приоритет. Он показывает, насколько важен процесс для системы: чем выше приоритет, тем чаще планировщик выделяет процессору этому процессу.
В Linux приоритет задаётся параметром nice — показателем «вежливости». Чем выше значение nice, тем менее настойчиво процесс просит ресурсы. Чем ниже nice, тем выше приоритет.
Диапазон значений:
Значение по умолчанию — 0.
Примеры:
Обычные пользователи могут повышать значение nice (уменьшать приоритет), а уменьшать nice (повышать приоритет) может только администратор.
Изменить приоритет уже запущенного процесса можно командой:
Где 1234 — PID процесса.
Процессы реального времени (realtime)
Иногда системе нужно реагировать мгновенно, без малейшей задержки. Даже несколько миллисекунд могут стать критичными: в звуке появится щелчок, кадры видео начнут теряться, контроллер оборудования не успеет вовремя среагировать. Для таких случаев в Linux существуют планировщики реального времени — SCHED_FIFO и SCHED_RR.
Они работают иначе, чем обычный режим SCHED_OTHER, который используется почти для всех программ — от пользовательских приложений до фоновых демонов. В SCHED_OTHER работает алгоритм Completely Fair Scheduler (CFS). Он следит, чтобы каждый активный процесс получил «справедливую» долю процессорного времени. У кого отняли процессор слишком рано — тому дадут чуть больше в следующий раз, у кого было слишком много — тот подождёт. За счёт этого система остаётся отзывчивой даже под нагрузкой.
В старых системах планирование строилось на фиксированных квантах — коротких промежутках времени, после которых процесс приостанавливался, а ЦП передавался следующему. CFS делает то же самое, но гибко — оценивает, сколько реально времени получил каждый процесс, и выравнивает нагрузку между всеми. Внутри этого режима приоритет задаётся параметром nice. Он определяет «вежливость» процесса: от –20 (максимальный приоритет) до +19 (минимальный). Например,
запускает архиватор с пониженным приоритетом. Система отдаёт процессор другим приложениям, а gzip работает в фоне, не мешая.
Режимы SCHED_FIFO и SCHED_RR подчиняются другим правилам. Это классы реального времени, где важна точность, а не равенство. Процесс с более высоким приоритетом получает CPU и выполняется, пока сам не освободит его.
SCHED_FIFO (First In, First Out) прост и прямолинеен. Он ставит процессы в очередь по приоритетам. Задача с высоким приоритетом выполняется первой и не уступит место, пока не завершится или не перейдёт в ожидание. Если такой процесс зациклится, система перестаёт отвечать: ядро не сможет переключиться ни на что другое.
SCHED_RR (Round Robin) решает эту проблему. Он похож на FIFO, но добавляет ограничение — квант времени. После его истечения процесс временно уступает место следующему с тем же приоритетом. Это предотвращает зависания и делает выполнение более предсказуемым.
Чтобы запустить программу в режиме реального времени, используют утилиту chrt. Например:
запускает процесс с планировщиком SCHED_FIFO и приоритетом 90 (приоритеты в этом классе задаются в диапазоне от 1 до 99).
Использовать такие приоритеты нужно осторожно. Один бесконечный цикл с SCHED_FIFO и высоким приоритетом способен полностью захватить процессор и «повесить» систему. На сервере это обернётся зависанием, после которого поможет только перезагрузка. Поэтому режимы реального времени применяются только там, где гарантированная реакция важнее всего — в промышленном управлении, телеметрии, звуковой обработке и видеостудиях.
Разделение планировщиков по классам — это способ ядра Linux обеспечить баланс между отзывчивостью, скоростью и точностью. SCHED_OTHER поддерживает справедливость, SCHED_FIFO — жёсткие гарантии, а SCHED_RR сочетает предсказуемость с безопасностью.
Мониторинг и настройка приоритетов
Отслеживать, как система распределяет процессорное время между задачами, удобнее всего через интерактивные утилиты top и htop. Они работают прямо в терминале и обновляют данные в реальном времени.
Команда top
запускает монитор процессов. Вверху экрана — общие показатели: загрузка CPU, число процессов, использование памяти и подкачки. Ниже — таблица всех активных задач. Для каждой строки указаны:
PID— идентификатор процесса,USER— владелец,PR— приоритет,NI— значение nice,%CPU— доля времени процессора,%MEM— использование памяти,S— состояние (R — выполняется, S — спит, Z — зомби),COMMAND— исполняемая команда.**
Пример вывода:
Здесь gzip работает с nice = 10, то есть у него пониженный приоритет, а python3 получает CPU чаще.
Чтобы изменить приоритет прямо из top, нажмите r, введите PID и новое значение nice. Например:
Приоритет изменится сразу, и колонка NI обновится на лету.
Для более наглядного интерфейса используйте htop.
Эта утилита показывает те же данные, но с цветной визуализацией нагрузки по ядрам и памяти. В верхней части — полосы активности CPU и RAM, ниже — список процессов.
Управление происходит стрелками и функциональными клавишами: F7 — повысить приоритет (уменьшить nice), F8 — понизить приоритет (увеличить nice). В колонках PRI и NI изменения видны сразу.**
Чтобы выйти, нажмите q.
Для проверки можно запустить параллельно ресурсоёмкий процесс:
и наблюдать в top или htop, как планировщик выделяет ему CPU, а другие задачи временно уступают ресурсы. Так наглядно видно, как работает система приоритетов и распределение процессорного времени в Linux.
Управление вводом-выводом: ionice
Когда процесс активно работает с диском, он может заметно замедлить всю систему. Особенно это чувствуется на серверах, где параллельно идут другие операции — база данных пишет логи, система подкачки активно читает и пишет, а пользователь ждёт отклика. Чтобы такие процессы не мешали остальным, в Linux предусмотрен инструмент ionice, который управляет приоритетами ввода-вывода.
Команда ionice -c2 -n7 rsync /data /backup запускает rsync с минимальным приоритетом по операции чтения и записи. Система будет давать этому процессу доступ к диску только тогда, когда другие задачи не занимают очередь. То есть бэкап выполнится медленнее, но не повлияет на работу активных приложений.
За этим механизмом стоит планировщик ввода-вывода ядра. Исторически использовался CFQ (Completely Fair Queuing), в новых системах — Blk-MQ, но принцип тот же: ядро управляет очередью запросов к диску и решает, в каком порядке обслуживать их. ionice сообщает планировщику, к какому классу приоритетов относится конкретный процесс.
Всего существует четыре класса планирования:
none (0) — стандартный режим. Если процесс запущен без ionice, его запросы обрабатываются как обычно, без специальных ограничений.
realtime (1) — самый высокий приоритет. Такие запросы выполняются первыми, даже если диск занят. Использовать этот режим стоит крайне осторожно: процесс может полностью заблокировать очередь и лишить систему отклика. Обычно его применяют для специализированных сервисов реального времени, например в аудиообработке.
best-effort (2) — режим по умолчанию. Внутри него можно задать уровень приоритета от 0 до 7: чем меньше число, тем выше приоритет. Команда ionice -c2 -n0 запустит процесс с максимальным доступом к диску, -n7 — с минимальным. Это удобно для фоновых операций вроде резервного копирования или архивации.
idle (3) — самый «вежливый» класс. Процесс выполняет ввод-вывод только тогда, когда диск полностью свободен. Это идеальный вариант для периодических задач, которые можно выполнять в фоне без спешки.
Проверить текущие параметры можно так:
Эта команда покажет, в каком классе и с каким приоритетом работает процесс.
На практике ionice часто комбинируют с nice, который регулирует приоритет по CPU. nice управляет вычислениями, ionice — диском. Вместе они позволяют тонко настроить поведение фоновых задач, чтобы сервер оставался отзывчивым даже во время резервного копирования, сборки пакетов или массовой архивации логов.

