Книга: Разработка ядра Linux
Вытеснение пространства ядра
Вытеснение пространства ядра
Ядро операционной системы Linux, в отличие от ядер большинства вариантов ОС Unix, является полностью преемптивным (вытесняемым, preemptible). В непреемптивных ядрах код ядра выполняется до завершения. Иными словами, планировщик не может осуществить планирование для выполнения другого задания, пока какое-либо задание выполняется в пространстве ядра — код ядра планируется на выполнение кооперативно, а не посредством вытеснения. Код ядра выполняется до тех пор, пока он не завершится (возвратит управление в пространство пользователя) или пока явно не заблокируется. С появлением серии ядер 2.6, ядро Linux стало преемптивным: теперь есть возможность вытеснить задание в любой момент, конечно, пока ядро находится в состоянии, когда безопасно производить перепланирование выполнения.
В таком случае когда же безопасно производить перепланирование? Ядро способно вытеснить задание, работающее в пространстве ядра, когда это задание не удерживает блокировку. Иными словами, блокировки используются в качестве маркеров тех областей, в которые задание не может быть вытеснено. Ядро рассчитано на многопроцессорность (SMP-safe), поэтому если блокировка не удерживается, то код ядра является реентерабельным и его вытеснять безопасно.
Первое изменение, внесенное для поддержки вытеснения пространства ядра, — это введение счетчика преемптивности preempt_count
в структуру thread_info
каждого процесса. Значение этого счетчика вначале равно нулю и увеличивается на единицу при каждом захвате блокировки, а также уменьшается на единицу при каждом освобождении блокировки. Когда значение счетчика равно нулю— ядро является вытесняемым. При возврате из обработчика прерывания, если возврат выполняется в пространство ядра, ядро проверяет значения переменных need_resched
и preempt_count
. Если флаг need_resched
установлен и значение счетчика preempt_count равно нулю, значит, более важное задание готово к выполнению и выполнять вытеснение безопасно. Далее активизируется планировщик. Если значение счетчика preempt_count
не равно нулю, значит, удерживается захваченная блокировка и выполнять вытеснение не безопасно. В таком случае возврат из обработчика прерывания происходит в текущее выполняющееся задание. Когда освобождаются все блокировки, удерживаемые текущим заданием, значение счетчика preempt_count
становится равным нулю. При этом код, осуществляющий освобождение блокировки, проверяет, не установлен ли флаг need_resched
. Если установлен, то активизируется планировщик. Иногда коду ядра необходимо иметь возможность запрещать или разрешать вытеснение в режиме ядра, что будет рассмотрено в главе 9.
Вытеснение пространства ядра также может произойти явно, когда задача блокируется в режиме ядра или явно вызывается функция schedule()
. Такая форма преемптивности ядра всегда поддерживалась, так как в этом случае нет необходимости в дополнительной логике, которая бы давала возможность убедиться, что вытеснение проводить безопасно. Предполагается, что если код явно вызывает функцию schedule()
, то точно известно, что перепланирование производить безопасно.
Вытеснение пространства ядра может произойти в следующих случаях.
• При возврате из обработчика прерывания в пространство ядра.
• Когда код ядра снова становится преемптивным.
• Если задача, работающая в режиме ядра, явно вызывает функцию schedule()
.
• Если задача, работающая в режиме ядра, переходит в приостановленное состояние, т.е. блокируется (что приводит к вызову функции schedule()
).
- Вытеснение и переключение контекста
- Вытеснение пространства пользователя
- 4 Центральный участок видимого пространства определяется периферическим зрением
- Вытеснение
- Пространства имён
- 3.2.5. Исследование адресного пространства
- 1.1 Режимы ядра и пользователя Windows
- Вытеснение процесса
- 2.1. Принципы организации выставочного пространства
- 3.8. Обновление ядра
- 3.8.2. Обновление ядра из RPM-пакета
- 3.8.3. Компиляция ядра