Приоритеты выполнения программного кода
Поскольку разные процессорные архитектуры реализуют разные подходы к управлению аппаратурой при помощи прерываний, разделяемых по приоритетам, операционная система Windows NT использует идеализированную схему, которая удовлетворяет особенностям всех аппаратных платформ. Практическая сторона данной схемы состоит в использовании процедур слоя аппаратный абстракций HAL, которые и берут на себя специфические особенности аппаратуры, позволяя создавать платформенно-независимый драйверный код.
Основой этой схемы абстрактных приоритетов прерываний является IRQL (interrupt request level) — уровень запроса на прерывание. Уровень IRQL представляет собой число, определяющее приоритет. Программный код, выполняющийся на данном уровне IRQL, не может быть прерван программным кодом, имеющим равный или более низкий IRQL. В таблице 6.1 приводятся уровни IRQL, используемые в Windows 2000/XP/Server 2003. Именно так уровни IRQL видятся драйверу, независимо от того, на каком процессоре или в какой шинной архитектуре приходится драйверу работать. Важно также и то, что в любой конкретный момент времени каждая инструкция (оператор программного кода) выполняется на одном определенном уровне приоритета со специфическим значением IRQL. Уровень IRQL входит в состав контекста выполнения каждого потока, следовательно, в любой момент времени операционной системе достоверно известен его текущий уровень IRQL.
Таблица 6.1. Уровни IRQL
Генерируется | Наименование | Назначение | |
Аппаратным обеспечением |
HIGH_LEVEL | Проверка компьютера и шинные ошибки | |
POWER_LEVEL | Прерывание по сбою в энергоснабжении | ||
IPI_LEVEL | Прерывания межпроцессорного взаимодействия для многопроцессорных систем | ||
CLOCK_LEVEL | Интервальный таймер | ||
PROFILE_LEVEL | Таймер профилирования | ||
DIRQL | Платформенно-зависимое число уровней для прерываний устройств ввода/вывода | ||
Программным обеспечением |
DISPATCH_LEVEL | Планирование потоков и выполнение отложенных процедурных вызовов (DPC) | |
APC_LEVEL | Выполнение асинхронных процедурных вызовов (1) | ||
PASSIVE_LEVEL | Уровень нормального исполнения потоков (0) |
В приведенной схеме значения IQRL аппаратных прерываний лежат в интервале выше DISPATCH_LEVEL и ниже PROFILE_LEVEL. Эти уровни еще встречаются в литературе под названием 'device IRQL', DIRQL — уровни IRQL устройств. Уровни выше PASSIVE_LEVEL называются повышенными (elevated IRQLs). Программные потоки, работающие на повышенных уровнях, могут быть вытеснены только потоками с более высоким уровнем IRQL. Такой способ работы с потоками называется в литературе dispatching, диспетчеризация.
Потоки, работающие на уровне PASSIVE_LEVEL, попадают под управление планировщика заданий (sheduler). Приоритеты, которые различает планировщик заданий для потоков с уровнем PASSIVE_LEVEL, принимают значения от 0 до 32 (MAXIMUM_PRIORITY) и называются в ряде источников 'приоритетом планирования'
(sheduler priority, 'приоритет планировщика').
Между потоками PASSIVE_LEVEL, имеющими приоритеты планирования Real-Time и Normal имеется существенное различие. Первые продолжают свою работу до тех пор, пока не появится поток с большим приоритетом, так что потоки низких приоритетов должны дожидаться, пока текущий поток RealTime не завершит работу естественным путем. Потоки с приоритетами Normal планируются по другим правилам. Для работы им выделяется определенный квант времени, после чего управление передается другим потокам такого же приоритета. Время от времени планировщик может повышать приоритет отложенного потока в пределах диапазона Normal, в результате чего все программные потоки среди потоков этой группы, даже имеющие самые низкие приоритеты, рано или поздно получают управление.
Таблица 6.2. Приоритеты планирования для потоков уровня PASSIVE_LEVEL IRQL
Приоритеты | Наименование | Назначение |
RealTime (Приоритеты реального времени) |
HIGH_PRIORITY (31) : |
Приоритеты системных программных потоков (программного кода режима ядра) |
: LOW_REALTIME_PRIORITY (16) |
||
Normal (Динамические приоритеты) |
Normal maximum (15) : |
Приоритеты потоков пользовательских приложений |
: Normal Idle (1) |
||
LOW_PRIORITY (0) | Системный поток обнуления страничной памяти |
Драйвер имеет возможность создавать системные программные потоки с приоритетами планирования, укладывающимися в диапазон RealTime и регулировать их приоритеты в этом диапазоне при помощи вызова KeSetPriorityThread (рекомендуемым DDK документацией значением для этой операции является LOW_REALTIME_PRIORITY, равное 16, см. заголовочные файлы wdm.h или ntddk.h). Подробнее вопросы работы с программными потоками будут рассмотрены в главе 10. Получить текущее значение приоритета планирования известного потока можно при помощи вызова KeQueryPriorityThread, в то время как получить текущее значение IRQL (при работе внутри самого потока режима ядра) можно при помощи вызова KeGetCurrentIrql, как это было сделано в коде драйвера Example, см. главу 3.
Значение приоритета системного потока сразу после его создания (без искусственного изменения) в Windows XP равно 8.
Что касается программных потоков пользовательского режима, то они могут иметь как приоритеты планирования из диапазона Normal, так и более низкие. Например, приоритет THREAD_BASE_PRIORITY_IDLE имеет численное значение — 15.