Inflight Trace Recorder (IFR) для ведения журнала трассировок

Средство записи трассировки (IFR) — это функция трассировки, которая позволяет поставщику трассировки, например драйверу режима ядра или драйверу UMDF, создавать набор циклических буферов в памяти, где сохраняются последние сообщения журнала. Сообщения журнала можно просмотреть с помощью отладчика.

IFR основан на трассировке программного обеспечения WPP. Основное преимущество IFR по сравнению с WPP заключается в том, что он включается автоматически и вам не нужно запускать сеансы трассировки заранее.

Применимо к:

  • Минимальная ОС: Windows 8 для разработчиков драйверов KMDF и WDM
  • Минимальная ОС: Windows 10 для разработчиков драйверов UMDF (2.15)

Включение inflight trace Recorder в Visual Studio

Сначала выполните действия, описанные в разделе Добавление трассировки программного обеспечения WPP в драйвер Windows.

Затем на странице свойств Project в разделе Свойства конфигурации WPP> Trace-Function> и Macro Options-Enable> Inflight Trace Recorder (Включить запись трассировки во время выполнения) выберите Да.

Наконец, только для UMDF есть еще один шаг: в разделе Трассировка WPP-Function> и Macro Options-Preprocessor> Definitions добавьте WPP_MACRO_USE_KM_VERSION_FOR_UM=1.

Включение inflight trace Recorder из командной строки

При редактировании файла .vcxproj вручную задайте следующие записи:

Для драйвера KMDF или WDM:

    <ClCompile Include=...>
        <WppEnabled>true</WppEnabled>
        <WppKernelMode>true</WppKernelMode>
        <WppRecorderEnabled>true</WppRecorderEnabled>
        ...
    </ClCompile>

Для драйвера UMDF:

    <ClCompile Include=...>
        <WppEnabled>true</WppEnabled>
        <WppRecorderEnabled>true</WppRecorderEnabled>
        <WppPreprocessorDefinitions>WPP_MACRO_USE_KM_VERSION_FOR_UM=1</WppPreprocessorDefinitions>
        ...
    </ClCompile>

Настройка параметров inflight trace Recorder

Вы можете настроить IFR, задав следующие необязательные записи реестра в разделе параметров драйвера.

Используйте следующие записи реестра:

LogPages: REG_DWORD

Задайте для параметра количество страниц для хранения журнала по умолчанию. Значение по умолчанию — "один".

VerboseOn: REG_DWORD

Значение по умолчанию равно нулю приводит к тому, что IFR регистрирует ошибки, предупреждения и информационные события. Задайте значение one, чтобы добавить подробные выходные данные в журнал.

WppRecorder_UseTimeStamp: REG_DWORD (доступно, начиная со сборки WDK 22557)

Драйверы устанавливают для этой записи значение , чтобы добавить метки времени в записи журнала, которые затем можно просмотреть с помощью !rcdrkd.rcdrlogdump или !wdfkd.wdflogdump.

WppRecorder_PreciseTimeStamp: REG_DWORD (доступно начиная со сборки WDK 22557)

Если вы хотите более точные метки времени, в дополнение к WppRecorder_UseTimeStamp добавьте WppRecorder_PreciseTimeStamp , используя тот же синтаксис, который показан выше.

Примеры

В следующих примерах добавьте строки между начальным и конечным примечаниями, чтобы задать для количества страниц журнала две и включить метки времени.

Для драйвера в режиме ядра:

[IfrSample_Service_Inst] 
DisplayName    = %IfrSample.SvcDesc%
ServiceType    = 1               ; SERVICE_KERNEL_DRIVER
StartType      = 3               ; SERVICE_DEMAND_START
ErrorControl   = 1               ; SERVICE_ERROR_NORMAL
ServiceBinary  = %12%\IfrSample.sys
; =============== START
AddReg = IfrSample_Service_Inst.AddReg
 
[IfrSample_Service_Inst.AddReg]
HKR, "Parameters", "LogPages", %REG_DWORD%, 2
HKR, "Parameters", "WppRecorder_UseTimeStamp", %REG_DWORD%, 1
; =============== END

[Strings]
REG_DWORD = 0x00010001

Для драйвера UMDF:

[IfrSampleUm_Install] 
UmdfLibraryVersion=$UMDFVERSION$
ServiceBinary=%13%\IfrSampleUm.dll
; =============== START
AddReg=IfrSampleUm_Install.AddReg
 
[IfrSampleUm_Install.AddReg]
HKR, "Parameters", "LogPages", %REG_DWORD%, 2
HKR, "Parameters", "WppRecorder_UseTimeStamp", %REG_DWORD%, 1
; =============== END

Отправка сообщений трассировки в журнал по умолчанию

Следуйте инструкциям в разделе Добавление трассировки программного обеспечения WPP в драйвер Windows. Пример:

  • В DriverEntry вызовите WPP_INIT_TRACING(DriverObject, RegistryPath).
  • В EvtDriverUnload вызовите WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)).

Теперь драйвер может вызывать функцию трассировки при необходимости. Пример: TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDriverCreate failed, %!STATUS!", ntStatus);

Дополнительные сведения см. в разделе WPP_INIT_TRACING и WPP_CLEANUP.

Отправка сообщений трассировки в пользовательский журнал

Это относится только к драйверам в режиме ядра (KMDF или WDM).

Для большинства драйверов достаточно хорошо подходит один журнал по умолчанию. Однако в некоторых сценариях полезно иметь отдельные буферы журналов для отдельных сущностей.

Например, при написании драйвера шины может потребоваться, чтобы у каждого дочернего устройства был собственный буфер. Затем можно использовать отладчик для дампа только журнала для определенного дочернего устройства.

Чтобы настроить пользовательские журналы, драйвер должен включать <WppRecorder.h>. Затем вызовите следующие API:

Драйвер также должен определить новый макрос трассировки, который принимает дескриптор журнала в качестве первого параметра. Пример см. в разделе Пример драйвера для тостера.

Добавление сведений о метке времени в пользовательский журнал

Если драйвер вызывает WppRecorderLogCreate для создания дополнительных дескрипторов журнала, можно включить метки времени для некоторых дескрипторов журнала, но не для других.

Для этого необходимо добавить одну строку в код драйвера для каждого дескриптора журнала, который должен использовать метки времени. Пример кода см. в разделе WppRecorderLogCreate.

Примечание

Эта функция доступна начиная со сборки WDK 22557. Сведения о выборе конкретного выпуска см. в разделе Сборка драйверов для различных версий Windows.

Просмотр сообщений трассировки в отладчике

Для драйверов KMDF и UMDF используйте !wdfkd.wdflogdump как обычно. Он выведет журнал платформы IFR и журнал IFR драйвера.

Для драйверов WDM используйте !rcdrkd.rcdrloglist и !rcdrkd.rcdrlogdump.