Давайте приглядимся к использованию к предопределенным IRQL, начиная с самого высокого уровня:
- Ядро использует высокий уровень (high), только когда оно останавливает систему в функции KeBugCheckEx и маскирует все прерывания.
- Уровень сбоя электропитания (power fail) впервые упоминается в исходных документах о конструкции Windows NT. Он определяет поведение системного кода при сбое электропитания, но этот IRQL никогда не использовался.
- Уровень межпроцессорного прерывания (interprocessor interrupt) используется для запроса выполнения действия на другом процессоре, например, для обновления кэш-памяти процессорного TLB, завершения работы системы или при аварийном отказе системы.
- Уровень часов (clock) используется для системных часов. С его помощью ядро отслеживает время суток, а также измеряет и выделяет потокам время центрального процессора.
- Системные часы реального времени (или другой источник, например, локальный таймер APIC) используют при включении профилирования ядра (при задействовании механизма измерения производительности) уровень profile.
При активном состоянии профилирования ядра его обработчик системного прерывания записывает адрес кода, который выполнялся в тот момент, когда возникло прерывание. Со временем создается таблица выборки адресов, которую можно извлечь и проанализировать с помощью инструментов.
Для настройки и просмотра сгенерированной при профилировании статистики можно использовать такое средство, как Kernrate, входящее в состав Windows Driver Kit (WDK). Дополнительная информация об использовании данного средства дана в эксперименте, проводимом с Kernrate.
- IRQL синхронизации (synchronization) используется внутри операционной системы кодом диспетчера и планировщика для защиты доступа к глобальному потоку планирования и к коду ожидания-синхронизации. Обычно этот уровень определяется как самый высокий сразу же после IRQL-уровней устройств.
- IRQL-уровни устройств (device) используются для определения приоритетов прерываний, связанных с устройствами. Порядок отображения уровней прерываний на IRQL-уровни показан в предыдущих статьях.
- Уровень скорректированной машинной проверки (corrected machine check) используется для оповещения операционной системы после серьезной, но скорректированной аппаратной неблагоприятной ситуации или ошибки, о которой через интерфейс Machine Check Error (MCE) сообщил центральный процессор или встроенное программное обеспечение.
- Уровень отложенного вызова процедуры и диспетчеризации (DPC/dispatch) и уровень асинхронного вызова процедуры (APC) относятся к программным прерываниям, генерируемым ядром и драйверами устройств. Более подробно вызовы DPC и APC будут рассмотрены позже.
- Самый низкий пассивный IRQL-уровень (passive) на самом деле вообще не является настоящим уровнем прерываний; он соответствует обычному выполнению потока и возможности возникновения всех прерываний.
Эксперимент: Использование средства профилирования ядра (Kernrate) для замера производительности.
Средство Kernel Profiler (Kernrate) можно использовать для включения таймера профилирования системы, сбора примеров кода, выполняемых при запусках таймера, и вывода итоговой информации о распределении процессорного времени между файлами образов задач и функциями. Оно может быть использовано для отслеживания времени центрального процессора, потребляемого отдельными процессами и (или) времени, проведенном в режиме ядра независимо от процессов (например, затраченном на процедуры обслуживания прерывания). Профилирование ядра применяется при необходимости разобраться в том, на что система тратит время.
В своей самой простой форме Kernrate предоставляет выборку затрат времени на каждый модуль ядра (например, на Ntoskrnl, драйверы и т. д.).
Например, после установки Windows Driver Kit попробуйте выполнить следующие действия.
- Откройте окно командной строки.
- Наберите cd C:\WinDDK\7600.16385.1\tools\other (путь к вашей установке WDKдля Windows 7/Server 2008R2).
- Наберите dir. Вы увидите каталоги для каждой платформы.
- Запустите образ, соответствующий вашей платформе (без аргументов или ключей). Например, для системы x86 используется образ i386\kernrate.exe.
- Во время работы Kernrate выполните на системе какие-нибудь другие действия. Например, запустите Windows Media Player и проиграйте какую-нибудь музыку, запустите игру, широко использующую графику, или сделайте что-нибудь в сети вроде вывода содержимого каталога на удаленном общем сетевом ресурсе.
- Нажмите Ctrl+C для остановки Kernrate. Это заставит Kernrate показать статистику за период выборки.
В следующем выводе выборки из Kernrate показано, что был запущен проигрыватель Windows Media Player, воспроизводящий фильм с диска:
C:\WinDDK\7600.16385.1\tools\Other\i386>kernrate.exe
/==============================\
< KERNRATE LOG >
\==============================/
Date: 2011/03/09 Time: 16:44:24
Machine Name: TEST-LAPTOP
Number of Processors: 2
PROCESSOR_ARCHITECTURE: x86
PROCESSOR_LEVEL: 6
PROCESSOR_REVISION: 0f06
Physical Memory: 3310 MB
Pagefile Total: 7285 MB
Virtual Total: 2047 MB
PageFile1: \??\C:\pagefile.sys, 4100MB
OS Version: 6.1 Build 7601 Service-Pack: 1.0
WinDir: C:\Windows
Kernrate Executable Location: C:\WINDDK\7600.16385.1\TOOLS\OTHER\I386
Kernrate User-Specified Command Line:
kernrate.exe
Kernel Profile (PID = 0): Source= Time,
Using Kernrate Default Rate of 25000 events/hit
Starting to collect profile data
***> Press ctrl-c to finish collecting profile data
===> Finished Collecting Data, Starting to Process Results
------------Overall Summary:--------------
P0 K 0:00:00.000 ( 0.0%) U 0:00:00.234 ( 4.7%) I 0:00:04.789 (95.3%)
DPC 0:00:00.000 ( 0.0%) Interrupt 0:00:00.000 ( 0.0%)
Interrupts= 9254, Interrupt Rate= 1842/sec.
P1 K 0:00:00.031 ( 0.6%) U 0:00:00.140 ( 2.8%) I 0:00:04.851 (96.6%)
DPC 0:00:00.000 ( 0.0%) Interrupt 0:00:00.000 ( 0.0%)
Interrupts= 7051, Interrupt Rate= 1404/sec.
TOTAL K 0:00:00.031 ( 0.3%) U 0:00:00.374 ( 3.7%) I 0:00:09.640 (96.0%)
DPC 0:00:00.000 ( 0.0%) Interrupt 0:00:00.000 ( 0.0%)
Total Interrupts= 16305, Total Interrupt Rate= 3246/sec.
Total Profile Time = 5023 msec
BytesStart BytesStop BytesDiff.
Available Physical Memory , 1716359168, 1716195328, -163840
Available Pagefile(s) , 5973733376, 5972783104, -950272
Available Virtual , 2122145792, 2122145792, 0
Available Extended Virtual , 0, 0, 0
Committed Memory Bytes , 1665404928, 1666355200, 950272
Non Paged Pool Usage Bytes , 66211840, 66211840, 0
Paged Pool Usage Bytes , 189083648, 189087744, 4096
Paged Pool Available Bytes, 150593536, 150593536, 0
Free System PTEs , 37322, 37322, 0
Total Avg. Rate
Context Switches , 30152, 6003/sec.
System Calls , 110807, 22059/sec.
Page Faults , 226, 45/sec.
I/O Read Operations , 730, 145/sec.
I/O Write Operations , 1038, 207/sec.
I/O Other Operations , 858, 171/sec.
I/O Read Bytes , 2013850, 2759/ I/O
I/O Write Bytes , 28212, 27/ I/O
I/O Other Bytes , 19902, 23/ I/O
-----------------------------
Results for Kernel Mode:
-----------------------------
OutputResults: KernelModuleCount = 167
Percentage in the following table is based on the Total Hits for the Kernel
Time 3814 hits, 25000 events per hit --------
Module Hits msec %Total Events/Sec
NTKRNLPA 3768 5036 98 % 18705321
NVLDDMKM 12 5036 0 % 59571
HAL 12 5036 0 % 59571
WIN32K 10 5037 0 % 49632
DXGKRNL 9 5036 0 % 44678
NETW4V32 2 5036 0 % 9928
FLTMGR 1 5036 0 % 4964
======================= END OF RUN ==================================
=================== NORMALENDOFRUN==============================
Общие итоги показывают, что система провела 0,3 % времени в режиме ядра, 3,7 % в пользовательском режиме, 96,0 % в простое, 0,0 % на уровне DPC и 0,0 % на уровне прерывания. Наиболее востребованным модулем был Ntkrnlpa.exe, ядро для машин с поддержкой расширения физического адреса (PhysicalAddressExtension, PAE) или NX. Вторым по востребованности модулем является nvlddmkm.sys, драйвер для видеокарты на машине, используемой для тестирования. В этом есть смысл, поскольку основная активность, проявляемая в системе, исходила от WindowsMediaPlayer, отправлявшего ввод-вывод видео на видеодрайвер.
Если у вас есть файлы символов, вы можете расширить отдельные модули и посмотреть затраченное время, разбитое по именам функций. Например, профилирование системы при быстром перетаскивании окна по экрану приведет к следующему выводу (который показан частично):
C:\WinDDK\7600.16385.1\tools\Other\i386>kernrate.exe -z ntkrnlpa -z win32k
/==============================\
< KERNRATE LOG >
\==============================/
Date: 2011/03/09 Time: 16:49:56
Time 4191 hits, 25000 events per hit --------
Module Hits msec %Total Events/Sec
NTKRNLPA 3623 5695 86 % 15904302
WIN32K 303 5696 7 % 1329880
INTELPPM 141 5696 3 % 618855
HAL 61 5695 1 % 267778
CDD 30 5696 0 % 131671
NVLDDMKM 13 5696 0 % 57057
--- Zoomed module WIN32K.SYS (Bucket size = 16 bytes, Rounding Down) --------
Module Hits msec %Total Events/Sec
BltLnkReadPat 34 5696 10 % 149227
memmove 21 5696 6 % 92169
vSrcTranCopyS8D32 17 5696 5 % 74613
memcpy 12 5696 3 % 52668
RGNOBJ::bMerge 10 5696 3 % 43890
HANDLELOCK::vLockHandle 8 5696 2 % 35112
--- Zoomed module NTKRNLPA.EXE (Bucket size = 16 bytes, Rounding Down) --------
Module Hits msec %Total Events/Sec
KiIdleLoop 3288 5695 87 % 14433713
READ_REGISTER_USHORT 95 5695 2 % 417032
READ_REGISTER_ULONG 93 5695 2 % 408252
RtlFillMemoryUlong 31 5695 0 % 136084
KiFastCallEntry 18 5695 0 % 79016
Вторым по востребованности модулем был Win32k.sys, драйвер системы управления окнами. Также высокое место в списке было у видеодрайвера и у Cdd.dll, глобального видеодрайвера, используемого для темы рабочего стола Aero с 3D-ускорением. Эти результаты вполне понятны, поскольку основная активность системы заключалась в прорисовке экрана.
Заметьте, что в расширенном отображении для Win32k.sys наиболее востребованными оказались функции, связанные с объединением, копированием и перемещением битов, основными GDI-операциями для прорисовки окна, перетаскиваемого по экрану.
Одним из важных ограничений, накладываемых на код, выполняемый на уровне DPC/dispatch или выше, является то, что он не может ждать объект, если это требует от планировщика выбрать для выполнения другой поток, что является недопустимой операцией, поскольку планировщик при планировании потоков зависит от программных прерываний DPC-уровня.
Другим ограничением является то, что на IRQL-уровне DPC/dispatch или выше может быть доступна только неперемещаемая область памяти.
Это правило фактически является побочным эффектом первого ограничения, поскольку попытка обращения к нерезидентной памяти приводит к ошибке обращения к странице. При возникновении такой ошибки диспетчер памяти инициирует дисковый ввод-вывод, а затем вынуждает ждать, пока драйвер файловой системы считает страницу с диска.
Это ожидание, в свою очередь, заставляет планировщик выполнить контекстное переключение (возможно, на поток простоя, idle, если запуска не ожидает ни один пользовательский поток), нарушая тем самым правило, по которому планировщик не может быть вызван, поскольку во время чтения диска код по-прежнему выполняется на IRQL-уровне DPC/dispatch или выше.
Еще одна проблема является следствием того факта, что завершение ввода-вывода происходит на уровне APC_LEVEL, следовательно, даже в тех случаях, когда ожидания не потребуется, ввод-вывод никогда не завершится, поскольку завершение APC не получит никакого шанса на выполнение.
При нарушении любого их этих двух ограничений происходит сбой системы с кодом аварийного завершения работы IRQL_NOT_LESS_OR_EQUAL (IRQL не является меньшим или равным) или DRIVER_IRQL_NOT_LESS_OR_EQUAL (IRQL драйвера не является меньшим или равным). Нарушение этих ограничений является распространенной ошибкой при создании драйверов устройств. В качестве средства, помогающего обнаружить ошибки подобного типа, можно использовать верификатор Windows Driver Verifier.