EnglishРусский Map

Модели вытеснения в Linux

title
Модели вытеснения в Linux
type
concept
summary
PREEMPT_NONE, PREEMPT_FULL и PREEMPT_LAZY - когда ядро вправе отобрать CPU у исполняемого потока
tags
linux, kernel, scheduling
created
2026-04-30
updated
2026-05-14
lang
ru
source_updated
2026-05-14
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Вытеснение (preemption) - это решение планировщика о том, когда ему разрешено прервать работающий поток и передать CPU другому. Разным нагрузкам подходят разные ответы, поэтому ядро Linux предлагает этот выбор в виде конфигурации времени сборки.

Три модели

PREEMPT_NONE - ядро почти никогда не прерывает исполняемый поток. Тот работает, пока сам не отдаст CPU: системный вызов, блокирующий I/O, явный sleep. Минимум переключений контекста, высокая пропускная способность, предсказуемое поведение под нагрузкой. Традиционный выбор по умолчанию для серверов.

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

PREEMPT_LAZY - компромиссный вариант, появившийся в Linux 6.12. Вытеснение разрешено, но планировщик старается дождаться естественных границ, прежде чем вмешиваться. Задумывался как прямая замена PREEMPT_NONE для нагрузок, требующих высокой пропускной способности.

Что изменилось в Linux 7.0

В Linux 7.0 убрали PREEMPT_NONE для современных процессорных архитектур, оставив PREEMPT_FULL и PREEMPT_LAZY. Большинство серверных дистрибутивов переключили своё значение по умолчанию на PREEMPT_LAZY. Для подавляющего большинства программ переход прошёл незаметно. Но там, где он заметен, последствия оказались серьёзными - см. linux-7-postgres-regression с примером нагрузки (PostgreSQL на машине с 96 vCPU), где изменение уронило пропускную способность вдвое: теперь планировщик может вытеснить поток, удерживающий spinlock прямо во время обработки page fault.

Почему "drop-in" на деле не drop-in

PREEMPT_NONE давал неявную и бесплатную гарантию для любого кода, удерживающего spinlock: даже если владелец блокировки делал что-то требующее обработки ядром (page fault, slow path), его не вытесняли до завершения работы. Код, написанный до PREEMPT_LAZY, мог негласно на это полагаться. С удалением этого режима любое предположение в духе "владелец освободит блокировку за наносекунды" обязано строго соблюдаться на практике - либо подкрепляться чем-то более надёжным, вроде restartable sequences.

Что происходит до того, как всё это приобретает значение

Модель вытеснения вступает в силу только после завершения загрузки. На фазе 4 в linux-kernel-startup (start_kernel) прерывания отключены почти всё время, а планировщик хоть и существует, но ещё не балансирует нагрузку. Настоящая многозадачность - мир, где решения о вытеснении действительно имеют значение, - начинается на фазе 6 с вызова sched_init_smp(). Общий порядок описан в linux-boot-phases.

Sub-pages