Обычно базовый приоритет процесса (а значит, и базовый приоритет первичного потока) по умолчанию равен значению из середины диапазонов приоритетов процессов (24, 13, 10, 8, 6 или 4). Однако базовый приоритет некоторых системных процессов (например, диспетчера сеансов, контроллера сервисов и сервера локальной аутентификации) несколько превышает значение по умолчанию для класса Normal (8). Более высокий базовый приоритет по умолчанию обеспечивает запуск потоков этих процессов с приоритетом выше 8. Чтобы изменить свой начальный базовый приоритет, такие системные процессы используют внутреннюю функцию NtSetInformationProcess.
Функции Windows API, связанные с планированием
Эти функции перечислены в таблице 6-14 (более подробную информацию см. в справочной документации Windows API).
Таблица 6-14. API-функции планирования и их назначение
Сопутствующие утилиты
B следующей таблице перечислены утилиты, сообщающие информацию о планировании потоков. Базовый приоритет процесса можно увидеть (и изменить) с помощью диспетчера задач, Process Explorer, Pview или Pviewer. Заметьте, что Process Explorer позволяет уничтожать отдельные потоки в любых процессах. Ho, конечно же, этой возможностью следует пользоваться с крайней осторожностью.
Приоритеты потоков можно просмотреть в оснастке Performance (Производительность), а также с помощью утилит Process Explorer, Plist, Pview, Pviewer и Pstat. Хотя повышение или понижение приоритета процесса может оказаться весьма полезным, изменение приоритетов индивидуальных потоков внутри процесса, как правило, не имеет смысла, потому что постороннему человеку не известно, что делают эти потоки и почему важны именно такие их относительные приоритеты.
Единственный способ задать начальный класс приоритета для процесса — использовать команду start в командной строке Windows. Если вы хотите, чтобы некая программа каждый раз запускалась с определенным приоритетом, то можете создать для нее ярлык и указать команду запуска, предварив ее cmd /с. Это приведет к появлению окна командной строки, выполнению команды и последующему закрытию этого окна. Например, чтобы запустить Notepad в процессе с низким приоритетом, в свойствах ярлыка должна быть задана команда cmd /с start /low notepad.exe.
ЭКСПЕРИМЕНТ: исследуем и задаем приоритеты процессов и потоков
Попробуйте провести такой эксперимент.
1. Наберите в командной строке start /realtime notepad. Ha экране появится окно Notepad.
2. Запустите утилиту Process Explorer или Process Viewer (Pviewer.exe) из Support Tools и выберите Notepad.exe из списка процессов, как показано ниже. Заметьте, что динамический приоритет потока Notepad равен 24. Это значение совпадает со значением приоритета реального времени на рис. 6-12.
3. Аналогичную информацию можно получить в диспетчере задач. Для его запуска нажмите клавиши Ctrl+Shift+Esc и перейдите на вкладку Processes (Процессы). Щелкните правой кнопкой мыши процесс Notepad.exe и выберите команду Set Priority (Приоритет). Вы увидите, что класс приоритета потока относится к Realtime (Реального времени), как показано на следующей иллюстрации.
Диспетчер системных ресурсов Windows
B Windows Server 2003 Enterprise Edition и Windows Server 2003 Data-center Edition включен необязательный компонент, который называется диспетчером системных ресурсов Windows (Windows System Resource Manager, WSRM). Он позволяет администратору настраивать правила политики, указывающие для процессов использование процессорного времени, параметры привязки к процессорам и лимиты на физическую и виртуальную память. Кроме того, WSRM может генерировать отчеты по использованию ресурсов, удобные для учета и проверки уровня обслуживания по договорам с пользователями.
Такие правила могут быть применены к конкретным приложениям, пользователям или группам и действовать в определенные периоды или постоянно.
После того как вы сформировали политику выделения ресурсов для управления определенными процессами, служба WSRM будет вести мониторинг потребления ими процессорного времени и регулировать их базовые приоритеты, если эти процессы будут использовать процессорного времени больше или меньше, чем было установлено вами.
Ограничение физической памяти достигается заданием максимального размера рабочего набора через функцию SetProcessWorkingSetSizeEx, а ограничение виртуальной памяти реализуется самой службой (о лимитах на объемы физической и виртуальной памяти см. главу 7). Если заданный лимит превышен, WSRM — в зависимости от настроек — может уничтожать процессы или создавать соответствующую запись в журнале событий. Последнее позволяет выявить процесс с утечкой памяти до того, как он займет всю переданную виртуальную память в системе. Заметьте, что лимиты на память, установленные в WSRM, не применяются к памяти Address Windowing Extensions (AWE), памяти больших страниц (large page memory) или памяти ядра (пулу подкачиваемых или неподкачиваемых страниц).
Приоритеты реального времени
Вы можете повысить или понизить приоритет потока любого приложения в динамическом диапазоне; однако, чтобы задать значение из диапазона реального времени, у вас должна быть привилегия Increase Scheduling Priority. Учтите, что многие важные системные потоки режима ядра выполняются в диапазоне приоритетов реального времени. Поэтому, если потоки слишком долго выполняются с приоритетом этого диапазона, они могут блокировать критичные системные функции (например в диспетчере памяти, диспетчере кэша или драйверах устройств).
ПРИМЕЧАНИЕ Как показано на следующей иллюстрации, где изображены уровни запросов прерываний (Interrupt Request Levels, IRQL) на платформе x86, в Windows имеется набор приоритетов, называемых приоритетами реального времени, но они не являются таковыми в общепринятом смысле этого термина, так как Windows не относится к операционным системам реального времени. Подробнее на эту тему см. врезку «Windows и обработка данных в реальном времени» в главе 3, а также статью «Real-Time Systems and Microsoft Windows NT» в MSDN Library.
Уровни прерываний и уровни приоритета
Как показано на следующей иллюстрации, потоки обычно выполняются при IRQL, равном 0 или 1. (Описание уровней прерываний в Windows см. в главе 3.) Потоки пользовательского режима всегда выполняются при IRQL, равном 0. Ввиду этого ни один поток пользовательского режима независимо от его приоритета не в состоянии блокировать аппаратные прерывания (хотя потоки с высоким приоритетом из диапазона реального времени способны блокировать важные системные потоки). При IRQL, равном 1, работают только APC режима ядра, поскольку они прерывают выполнение потоков (об APC см. главу 3). Кроме того, потоки, выполняемые в режиме ядра, могут повышать IRQL, например при обработке системного вызова, требующего диспетчеризации потоков.
Состояния потоков
Прежде чем перейти к алгоритмам планирования потоков, вы должны разобраться, в каких состояниях могут находиться потоки в процессе выполнения в Windows 2000 и Windows XR Соответствующая схема дана на рис. 6-13 [числовые значения отражают показатели счетчика производительности Thread: thread state (Поток-. Состояние потока)].
Вот что представляют собой состояния потока.
• Ready (готов) Поток в состоянии готовности ожидает выполнения. Выбирая следующий поток для выполнения, диспетчер принимает во внимание только пул потоков, готовых к выполнению.
• Standby (простаивает) Поток в этом состоянии уже выбран следующим для выполнения на конкретном процессоре. B подходящий момент диспетчер переключает контекст на этот поток. B состоянии Standby может находиться только один поток для каждого процессора в системе. Заметьте, что поток может быть вытеснен даже в этом состоянии (если, например, до начала выполнения потока, который пока находится в состоянии Standby, к выполнению будет готов поток с более высоким приоритетом).
• Running (выполняется) Поток переходит в это состояние и начинает выполняться сразу после того, как диспетчер переключает на него контекст. Выполнение потока прекращается, как только он завершается, вытесняется потоком с более высоким приоритетом, переключает контекст на другой поток, самостоятельно переходит в состояние ожидания или истекает выделенный ему квант процессорного времени (и другой поток с тем же приоритетом готов к выполнению).
• Waiting (ожидает) Поток входит в состояние Waiting несколькими способами. Он может самостоятельно начать ожидание на синхронизирующем объекте или его вынуждает к этому подсистема окружения. По окончании ожидания поток — в зависимости от приоритета — либо немедленно начинает выполняться, либо переходит в состояние Ready.