• Короткие или длинные Значение 1 указывает на длинные кванты, а 2 — на короткие. Если это поле равно 0 или 3, используются кванты по умолчанию (короткие в Windows 2000 Professional или Windows XP и длинные в системах Windows Server).
• Переменные или фиксированные Если задано значение 1, кванты потоков активного процесса могут варьироваться, а если задано значение 2 — нет. Если это поле равно 0 или 3, используется настройка по умолчанию (переменные в Windows 2000 Professional или Windows XP и фиксированные в системах Windows Server).
• Динамическое приращение кванта потока активного процесса Это поле (хранящееся в переменной ядра PsPrioritySeparatiori) может быть равно 0, 1 или 2 (значение 3 недопустимо и интерпретируется как 2) и представляет собой индекс в трехэлементном байтовом массиве (PspForegroundQuantum), используемом для расчета квантов потоков активного процесса. Кванты потоков фоновых процессов определяются первым элементом этого массива. Возможные значения в PspForegroundQuantum перечислены в таблице 6-l6.
Заметьте, что при использовании диалогового окна Performance Options (Параметры быстродействия) доступны лишь две комбинации: короткие кванты с утроением в активном процессе или длинные без изменения в таком процессе. Ho прямое редактирование параметра Win32PrioritySeparation в реестре позволяет выбирать и другие комбинации.
Известно, что вопрос «Какому потоку отдать процессорное время?» Windows 2000 решает, исходя из приоритетов. Ho как этот подход работает на практике? Следующие разделы иллюстрируют, как вытесняющая многозадачность, управляемая на основе приоритетов, действует на уровне потоков.
Во-первых, поток может самостоятельно освободить процессор, перейдя в состояние ожидания на каком-либо объекте (например, событии, мьютек-ce, семафоре, порте завершения ввода-вывода, процессе, потоке, оконном сообщении и др.) путем вызова одной из многочисленных Windows-функций ожидания (скажем, WaitForSingleObjectvum WaitForMultipleObjects). Ожидание на объектах было рассмотрено в главе 3.
Ha рис. 6-19 показано, как поток входит в состояние ожидания и как Windows выбирает новый поток для выполнения.
Ha рис. 6-19 поток (верхний блок) самостоятельно освобождает процессор, в результате чего к процессору подключается другой поток из очереди (отмеченный кольцом в колонке Running). Исходя из этой схемы, можно подумать, что приоритет потока, освобождающего процессор, снижается, но это не так — он просто переводится в очередь ожидания выбранных им объектов. A что происходит с оставшейся частью кванта этого потока? Когда поток входит в состояние ожидания, квант не сбрасывается. Как уже говорилось, после успешного завершения ожидания квант потока уменьшается на одну единицу, что эквивалентно трети интервала таймера (исключение составляют потоки с приоритетом от 14 и выше, у которых после ожидания квант сбрасывается).
B этом сценарии поток с более низким приоритетом вытесняется готовым к выполнению потоком с более высоким приоритетом. Такая ситуация может быть следствием двух обстоятельств:
• завершилось ожидание потока с более высоким приоритетом (т. е. произошло событие, которого он ждал);
• приоритет потока увеличился или уменьшился.
B любом из этих случаев Windows решает, продолжить выполнение текущего потока или вытеснить его потоком с более высоким приоритетом.
ПРИМЕЧАНИЕ Потоки пользовательского режима могут вытеснять потоки режима ядра. To есть режим выполнения потока значения не имеет — определяющим фактором является его приоритет.
Когда поток вытесняется, он помещается в начало очереди готовых потоков соответствующего уровня приоритета. Эту ситуацию иллюстрирует рис. 6-20.
Ha рис. 6-20 поток с приоритетом 18 выходит из состояния ожидания и вновь захватывает процессор, вытесняя выполняемый в этот момент поток (с приоритетом 16) в очередь готовых потоков. Заметьте, что вытесненный поток помещается не в конец, а в начало очереди. После завершения вытеснившего потока вытесненный сможет отработать остаток своего кванта.
Когда поток израсходует свой квант процессорного времени, Windows должна решить, следует ли понизить его приоритет и подключить к процессору другой поток.
Снизив приоритет потока, Windows ищет более подходящий для выполнения поток (таким потоком, например, будет любой из очереди готовых потоков с приоритетом выше нового приоритета текущего потока). Если Windows оставляет приоритет потока прежним и в очереди готовых потоков есть другие потоки с тем же приоритетом, она выбирает из очереди следующий поток с тем же приоритетом, а выполнявшийся до этого поток перемещает в хвост очереди (задавая ему новую величину кванта и переводя его из состояния Running в состояние Ready). Этот случай иллюстрирует рис. 6-21. Если ни один поток с тем же приоритетом не готов к выполнению, текущему потоку выделяется еще один квант процессорного времени.
Завершаясь (после возврата из основной процедуры и вызова ExitThread или из-за уничтожения вызовом TerminateThread), поток переходит в состояние Terminated. Если в этот момент ни один описатель его объекта «поток» не открыт, поток удаляется из списка потоков процесса, и соответствующие структуры данных освобождаются.
Контекст потока и процедура его переключения зависят от архитектуры процессора. B типичном случае переключение контекста требует сохранения и восстановления следующих данных:
• указателя команд;
• указателей на стек ядра и пользовательский стек;
• указателя на адресное пространство, в котором выполняется поток (каталог таблиц страниц процесса).
Ядро сохраняет эту информацию, заталкивая ее в текущий стек ядра, обновляя указатель стека и сохраняя его в блоке KTHREAD потока. Далее указатель стека ядра устанавливается на стек ядра нового потока и загружается контекст этого потока. Если новый поток принадлежит другому процессу, в специальный регистр процессора загружается адрес его каталога таблиц страниц, в результате чего адресное пространство этого процесса становится доступным (о трансляции адресов см. в главе 7). При наличии отложенной APC ядра запрашивается прерывание IRQL уровня 1. B ином случае управление передается загруженному для нового потока указателю команд, и выполнение этого потока возобновляется.
Если нет ни одного потока, готового к выполнению на процессоре, Windows подключает к данному процессору поток простоя (процесса Idle). Для каждого процессора создается свой поток простоя.
Разные утилиты для просмотра процессов в Windows по-разному называют процесс Idle. Диспетчер задач и Process Explorer обозначают его как «System Idle Process», Process Viewer — как «Idle», Pstat — как «Idle Process», Process Explode и Tlist — как «System Process», a Qslice — как «SystemProcess». Windows сообщает, что приоритет потока простоя равен 0. Ho на самом деле у него вообще нет уровня приоритета, поскольку он выполняется лишь в отсутствие других потоков. (Вспомните, что на нулевом уровне приоритета в Windows работает лишь поток обнуления страниц; см. главу 7.)