Вытеснение и переключение контекста
Вытеснение и переключение контекста
Переключение контекста — это переключение от одной, готовой к выполнению задачи к другой. Это переключение производится с помощью функции context_switch(), определенной в файле kernel/sched.c. Данная функция вызывается функцией schedule(), когда новый процесс выбирается для выполнения. При этом выполняются следующие шаги.
• Вызывается функция switch_mm(), которая определена в файле include/asm/mmu_context.h и предназначена для переключения от виртуальной памяти старого процесса к виртуальной памяти нового процесса.
• Вызывается функция switch_to(), определенная в файле include/asm/system.h, для переключения от состояния процессора предыдущего процесса к состоянию процессора нового процесса. Эта процедура включает восстановление информации стека ядра и регистров процессора.
Ядро должно иметь информацию о том, когда вызывать функцию schedule(). Если эта функция будет вызываться только тогда, когда программный код вызывает ее явно, то пользовательские программы могут выполняться неопределенное время. Поэтому ядро поддерживает флаг need_resched для того, чтобы сигнализировать, необходимо ли вызывать функцию schedule() (табл. 4.2). Этот флаг устанавливается функцией scheduler_tick(), когда процесс истрачивает свой квант времени, и функцией try_to_wake_up(), когда процесс с приоритетом более высоким, чем у текущего процесса, возвращается к выполнению. Ядро проверяет значение этого флага, и если он установлен, то вызывается функция schedule() для переключения на новый процесс. Этот флаг является сообщением ядру о том, что планировщик должен быть активизирован по возможности раньше, потому что другой процесс должен начать выполнение.
Таблица 4.2. Функции для управления флагом need_resched
Функция Назначение set_tsk_need_resched(task) Установить флаг need_resched для данного процесса clear_tsk_need_resched(task) Очистить флаг need_resched для данного процесса need_resched() Проверить значение флага need_resched для данного процесса. Возвращается значение true, если этот флаг установлен, и false, если не установленВо время переключения в пространство пользователи или при возврате из прерывания, значение флага need_resched проверяется. Если он установлен, то ядро активизирует планировщик перед тем, как продолжить работу.
Этот флаг не является глобальной переменной, так как обращение к дескриптору процесса получается более быстрым, чем обращение к глобальным данным (из-за скорости обращения к переменной current и потому, что соответствующие данные могут находиться в кэше). Исторически, этот флаг был глобальным в ядрах до серии 2.2. В ядрах серий 2.2 и 2.4 этот флаг принадлежал структуре task_struct и имел тип int. В серии ядер 2.6 этот флаг перемещен в один определенный бит специальной переменной флагов структуры thread_info. Легко видеть, что разработчики ядра никогда не могут быть всем довольны.