Ядро состоит из набора функций, находящихся в файле Ntoskrnl.exe. Этот набор предоставляет основные механизмы (службы диспетчеризации потоков и синхронизации), используемые компонентами исполняющей системы, а также поддержкой архитектурно-зависимого оборудования низкого уровня (например, диспетчеризацией прерываний и исключений), которое имеет отличия в архитектуре каждого процессора.
Код ядра написан главным образом на C, с ассемблерным кодом, предназначенным для задач, требующих доступа к специальным инструкциям и регистрам процессора, доступ к которым из кода на языке C затруднен.
Подобно различным вспомогательным функциям, ряд функций ядра документированы в WDK (и их описание может быть найдено при поиске функций, начинающихся с префикса Ke), поскольку они нужны для реализации драйверов устройств.
Содержание:
Объекты ядра.
Ядро предоставляет низкоуровневую базу из четко определенных, предсказуемых примитивов и механизмов операционной системы, позволяющую высокоуровневым компонентам исполняющей системы выполнять свои функции. Само ядро отделено от остальной исполняющей системы путем реализации механизмов операционной системы и уклонения от выработки политики. Оно оставляет почти все политические решения, за исключением планирования и диспетчеризации потоков, реализуемых ядром, за исполняющей системой.
За пределами ядра исполняющая система представляет потоки и другие ресурсы совместного использования в виде объектов. Эти объекты требуют некоторых издержек, например, на дескрипторы для управления ими, на проверки безопасности для их защиты и на ресурсные квоты, выделяемые при их создании.
В ядре, реализующем набор менее сложных объектов, называемых «объектами ядра», подобные издержки исключены, что помогает ядру управлять основной обработкой и поддерживать создание исполняющих объектов. Большинство объектов уровня исполнения инкапсулируют один или несколько объектов ядра, принимая их, определенные в ядре свойства.
Один набор объектов ядра, называемых «управляющими объектами», определяет семантику управления различными функциями операционной системы.
В этот набор включены объекты асинхронного вызова процедур — APC, отложенного вызова процедур — deferred procedure call (DPC), и несколько объектов, используемых диспетчером ввода-вывода, например, объект прерывания.
Еще один набор объектов ядра, известных как «объекты-диспетчеры», включает возможности синхронизации, изменяющие или влияющие на планирование потоков. Объекты-диспетчеры включают поток ядра, мьютекс (называемый среди специалистов «мутантом»), событие, пару событий ядра, семафор, таймер и таймер ожидания. Исполняющая система использует функции ядра для создания экземпляров объектов ядра, работы с ними и создания более сложных объектов, предоставляемых в пользовательском режиме.
Область ядра, относящаяся к управлению процессором, и блок управления (KPCR и KPRCB).
Для хранения специфических для процессора данных ядром используется структура данных, называемая областью, относящейся к управлению процессором, или KPCR (KernelProcessorControlRegion). KPCR содержит основную информацию, такую как процессорная таблица диспетчеризации прерываний (interrupt dispatch table, IDT), сегмент состояния задачи (task-state segment, TSS) и таблица глобальных дескрипторов (globaldescriptortable, GDT). Она также включает состояние контроллера прерываний, которое используется вместе с другими модулями, такими как ACPI-драйвер и HAL.
Для обеспечения простого доступа к KPCR ядро хранит указатель на эту область в регистре fs на 32-разрядной системе Windows и в регистре gs на Windows-системе x64. На системах IA64 KPCR всегда находится по адресу 0xe0000000ffff0000.
KPCR также содержит вложенную структуру данных, которая называется блоком управления процессором (kernelprocessorcontrolblock, KPRCB). В отличие от области KPCR, которая документирована для драйверов сторонних производителей и для других внутренних компонентов ядра Windows, KPRCB является закрытой структурой, используемой только кодом ядра, который находится в файле Ntoskrnl.exe.
В этом блоке содержится:
- информация о планировании (такая как текущий, следующий и приостановленный потоки, предназначенные для выполнения на процессоре);
- предназначенная для процессора база данных диспетчера (включающая готовые очереди для каждого приоритетного уровня);
- DPC-очередь;
- информация о производителе центрального процессора и идентификационная информация (модель, степпинг, скорость, биты особенностей);
- информация о топологии центрального процессора и о технологии доступа к неоднородной памяти — NUMA (информация об узле, о количестве логических процессоров в каждом ядре и т. д.);
- информация о размерах кэш-памяти;
- информация об учете времени (такая как время DPC и обработки прерывания) и многое другое.
В KPRCB также содержится вся статистика процессора, такая как статистика ввода-вывода, статистика диспетчера кэша, статистика DPC и статистика диспетчера памяти. И наконец, KPRCB иногда используется для хранения структур выравнивания границ кэша для каждого процессора, необходимых для оптимизации доступа к памяти, особенно на NUMA-системах. Например, система невыгружаемого и выгружаемого пула со стороны выглядит как списки, хранящиеся в KPRCB.
Эксперимент: просмотр KPCR и KPRCB.
Содержимое KPCR и KPRCB можно просмотреть, используя команды отладки ядра !pcr и !prcb. Без пометок отладчик по умолчанию покажет информацию для центрального процессора 0; но вы можете указать центральный процессор, добавив после команды его номер (например, !pcr 2).
В следующем примере показано, как выглядит вывод команд !pcr и !prcb.
Если в системе имелись задержанные DPC-вызовы, эта информация также будет отображена на экране.
lkd> !pcr
KPCR for Processor 0 at 81d09800:
Major 1 Minor 1
NtTib.ExceptionList: 9b31ca3c
NtTib.StackBase: 00000000
NtTib.StackLimit: 00000000
NtTib.SubSystemTib: 80150000
NtTib.Version: 1c47209e
NtTib.UserPointer: 00000001
NtTib.SelfTib: 7ffde000
SelfPcr: 81d09800
Prcb: 81d09920
Irql: 00000002
IRR: 00000000
IDR: ffffffff
InterruptMode: 00000000
IDT: 82fb8400
GDT: 82fb8000
TSS: 80150000
CurrentThread: 86d317e8
NextThread: 00000000
IdleThread: 81d0d640
DpcQueue:
lkd> !prcb
PRCB for Processor 0 at 81d09920:
Current IRQL – 0
Threads-- Current 86d317e8 Next 00000000 Idle 81d0d640
Number 0 SetMember 1
Interrupt Count -- 294ccce0
Times -- Dpc 0002a87f Interrupt 00010b87
Kernel 026270a1 User 00140e5e
Для непосредственного вывода дампа структур данных _KPCR и _KPRCB можно воспользоваться командой dt, поскольку обе команды отладки дают вам адреса структур (которые для наглядности выделены в предыдущем выводе жирным шрифтом). Например, если нужно определить скорость процессора, можно с помощью следующей команды посмотреть на поле MHz:
lkd> dt nt!_KPRCB 81d09920 MHz
+0x3c4 MHz : 0xbb4
lkd> ? bb4
Evaluate expression: 2996 = 00000bb4
На данной машине процессор был запущен на частоте около 3 ГГц.