Блог инженера

History is written by its contributors

Многозадачность в Linux: вытесняющая vs невытесняющая

2025-11-29 время чтения 5 мин Operating Systems Ilya Brin

Многозадачность - это способность операционной системы выполнять несколько задач одновременно. Но “одновременно” - это иллюзия. На самом деле процессор переключается между задачами так быстро, что создаётся впечатление параллельной работы.

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

Что такое многозадачность

Представьте повара на кухне. Он готовит несколько блюд: варит суп, жарит мясо, печёт пирог. Он не может делать всё одновременно - у него две руки. Но он переключается между задачами: помешал суп, перевернул мясо, проверил пирог.

Так же работает процессор. Он выполняет одну задачу, потом переключается на другую, потом на третью. Переключение происходит так быстро (тысячи раз в секунду), что кажется, будто всё работает параллельно.

Два типа многозадачности

Невытесняющая многозадачность (Cooperative Multitasking)

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

Как это работает:

Программа выполняется до тех пор, пока сама не решит передать управление операционной системе. Она может работать секунду, минуту или вообще никогда не отдать управление.

Проблемы:

  1. Зависание системы - если одна программа зависла и не отдаёт управление, вся система встаёт
  2. Недобросовестные программы - программа может захватить процессор и не отпускать
  3. Нет гарантий - нельзя гарантировать время отклика

Пример из истории:

Windows 3.1 и Mac OS до версии X использовали невытесняющую многозадачность. Если программа зависала, приходилось перезагружать весь компьютер.

Современное применение:

Сегодня невытесняющая многозадачность используется внутри программ для кооперативных корутин (goroutines в Go, async/await в JavaScript), но не на уровне операционной системы.

Вытесняющая многозадачность (Preemptive Multitasking)

В вытесняющей многозадачности операционная система принудительно забирает управление у программы через определённые интервалы времени. Это как модератор дискуссии: вы говорите, но через минуту модератор вас прерывает и даёт слово другому.

Как это работает:

Операционная система использует таймер (обычно срабатывает каждые 1-10 миллисекунд). Когда таймер срабатывает, происходит прерывание, и планировщик решает, какую задачу выполнять дальше.

Преимущества:

  1. Отзывчивость - система всегда реагирует на действия пользователя
  2. Справедливость - каждая программа получает процессорное время
  3. Стабильность - зависшая программа не блокирует всю систему
  4. Приоритеты - важные задачи могут получать больше времени

Linux использует вытесняющую многозадачность.

Как работает вытесняющая многозадачность в Linux

Квант времени (Time Slice)

Каждому процессу выделяется квант времени - промежуток, в течение которого он может выполняться. В Linux это обычно 1-10 миллисекунд.

Когда квант истекает, планировщик:

  1. Сохраняет состояние текущего процесса (регистры, счётчик команд)
  2. Выбирает следующий процесс для выполнения
  3. Восстанавливает состояние выбранного процесса
  4. Передаёт ему управление

Этот процесс называется переключением контекста (context switch).

Планировщик (Scheduler)

Планировщик - это часть ядра Linux, которая решает, какой процесс выполнять следующим.

Критерии выбора:

  1. Приоритет - процессы с высоким приоритетом выполняются чаще
  2. Время ожидания - процессы, которые долго ждали, получают преимущество
  3. Тип задачи - интерактивные задачи (GUI) важнее фоновых
  4. CPU affinity - привязка к конкретному ядру процессора

Классы планирования в Linux:

  1. SCHED_NORMAL - обычные процессы (99% программ)
  2. SCHED_FIFO - реального времени, FIFO очередь
  3. SCHED_RR - реального времени, Round-Robin
  4. SCHED_BATCH - фоновые задачи
  5. SCHED_IDLE - самый низкий приоритет

Приоритеты

В Linux есть два типа приоритетов:

Nice value (-20 до +19):

  • -20 - самый высокий приоритет
  • 0 - нормальный приоритет
  • +19 - самый низкий приоритет

Обычный пользователь может только понижать приоритет своих процессов. Повышать может только root.

Real-time priority (1-99):

  • Используется для задач реального времени
  • Приоритет 99 - самый высокий
  • Требует root-прав

Состояния процесса

Процесс в Linux может находиться в нескольких состояниях:

  1. Running (R) - выполняется или готов к выполнению
  2. Sleeping (S) - ждёт события (ввод-вывод, сигнал)
  3. Uninterruptible Sleep (D) - ждёт ввод-вывод, нельзя прервать
  4. Stopped (T) - остановлен (Ctrl+Z)
  5. Zombie (Z) - завершился, но родитель не прочитал статус

Планировщик выбирает только из процессов в состоянии Running.

Почему важно понимать разницу

1. Производительность приложений

Если ваше приложение выполняет длительные вычисления без переключения контекста, оно может показаться пользователю “зависшим”, даже если технически оно работает.

Плохо:

// Блокирует поток на 10 секунд
func ProcessData(data []byte) {
    for i := 0; i < 10000000000; i++ {
        // Вычисления
    }
}

Хорошо:

// Периодически отдаёт управление
func ProcessData(data []byte) {
    for i := 0; i < 10000000000; i++ {
        // Вычисления
        
        if i % 1000000 == 0 {
            runtime.Gosched() // Отдать управление другим горутинам
        }
    }
}

2. Отзывчивость системы

Понимание приоритетов помогает правильно настроить систему. Например, GUI приложения должны иметь более высокий приоритет, чем фоновые задачи.

# Запустить с низким приоритетом
nice -n 19 ./background-task

# Изменить приоритет работающего процесса
renice -n 10 -p 1234

3. Реальное время

Для задач реального времени (аудио, видео, управление оборудованием) критично понимать, как работает планировщик.

# Запустить с приоритетом реального времени
chrt -f 50 ./realtime-app

4. Отладка проблем

Когда система “тормозит”, понимание многозадачности помогает найти причину:

# Посмотреть загрузку процессора по процессам
top

# Посмотреть переключения контекста
vmstat 1

# Посмотреть приоритеты процессов
ps -eo pid,ni,pri,comm

Многоядерность и многозадачность

На многоядерном процессоре несколько задач действительно выполняются одновременно - каждое ядро работает независимо.

Но:

Если у вас 4 ядра и 100 процессов, планировщик всё равно переключает их на каждом ядре.

Важные концепции:

  1. CPU affinity - привязка процесса к конкретному ядру
  2. Load balancing - распределение нагрузки между ядрами
  3. Cache locality - процесс лучше работает на том же ядре
# Привязать процесс к ядрам 0 и 1
taskset -c 0,1 ./my-app

# Посмотреть на каком ядре работает процесс
ps -eo pid,psr,comm

Практические советы

1. Не блокируйте главный поток

В GUI приложениях длительные операции выполняйте в фоновых потоках.

2. Используйте правильные приоритеты

  • Интерактивные задачи - нормальный или повышенный приоритет
  • Фоновые задачи - пониженный приоритет
  • Задачи реального времени - SCHED_FIFO или SCHED_RR

3. Минимизируйте переключения контекста

Частые переключения контекста снижают производительность. Группируйте работу в батчи.

4. Учитывайте NUMA

На серверах с несколькими процессорами память может быть “ближе” к одним ядрам и “дальше” к другим. Это влияет на производительность.

# Посмотреть NUMA топологию
numactl --hardware

# Запустить на конкретном NUMA узле
numactl --cpunodebind=0 --membind=0 ./my-app

Заключение

Многозадачность в Linux - это вытесняющая многозадачность, где операционная система принудительно переключает процессы.

Ключевые моменты:

  1. Вытесняющая многозадачность обеспечивает отзывчивость и стабильность
  2. Планировщик решает, какой процесс выполнять
  3. Приоритеты влияют на распределение процессорного времени
  4. Переключение контекста имеет накладные расходы
  5. Многоядерность позволяет истинный параллелизм

Понимание этих концепций помогает:

  • Писать более эффективные приложения
  • Правильно настраивать систему
  • Отлаживать проблемы производительности
  • Работать с задачами реального времени

Linux предоставляет мощные инструменты для управления многозадачностью. Используйте их с умом.

Дополнительные ресурсы:

comments powered by Disqus