Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Esta seção descreve como usar a API de modo kernel do Rastreamento de Eventos para Windows (ETW) para adicionar o rastreamento de eventos aos drivers do modo kernel. A API de modo kernel ETW foi introduzida com o Windows Vista e não é suportada em sistemas operacionais anteriores. Use o rastreamento de software WPP ou o rastreamento de eventos WMI se o driver precisar oferecer suporte à funcionalidade de rastreamento no Windows 2000 e posterior.
Sugestão
Para ver o código de exemplo que mostra como implementar o ETW usando o Kit de Driver do Windows (WDK) e o Visual Studio, consulte o exemplo Eventdrv.
Nesta secção:
Workflow - Adicionando rastreamento de eventos ao Kernel-Mode drivers
1. Decida o tipo de eventos a gerar e onde publicá-los
2. Crie um manifesto de instrumentação que defina o provedor, os eventos e os canais
3. Compile o manifesto de instrumentação usando o compilador de mensagens (Mc.exe)
7. Teste o driver para verificar o suporte ao ETW
Fluxo de trabalho - Adicionando rastreamento de eventos a drivers de Kernel-Mode
1. Decida o tipo de eventos a realizar e onde publicá-los
Antes de começar a codificar, deves decidir que tipo de eventos desejas que o driver registre através do Rastreamento de Eventos para Windows (ETW). Por exemplo, talvez você queira registrar eventos que podem ajudá-lo a diagnosticar problemas depois que o driver é distribuído ou eventos que podem ajudá-lo enquanto desenvolve o driver. Para obter informações, consulte Referência do log de eventos do Windows.
Os tipos de eventos são identificados com canais. Um canal é um fluxo nomeado de eventos do tipo Admin, Operacional, Analítico ou Debug direcionado a um público específico, semelhante a um canal de televisão. Um canal transmite os eventos do provedor de eventos para os logs e aos consumidores de eventos. Para obter informações, consulte Definindo canais.
Durante o desenvolvimento, você provavelmente está interessado em rastrear eventos que ajudam a depurar seu código. Esse mesmo canal pode ser usado no código de produção para ajudar a solucionar problemas que possam aparecer após a implantação do driver. Você também pode querer rastrear eventos que podem ser usados para medir o desempenho; esses eventos podem ajudar os profissionais de TI a ajustar o desempenho do servidor e podem ajudar a identificar gargalos de rede.
2. Crie um manifesto de instrumentação que defina o provedor, os eventos e os canais
O manifesto de instrumentação é um arquivo XML que fornece uma descrição formal dos eventos que um provedor irá gerar. O manifesto de instrumentação identifica o provedor de eventos, especifica o canal ou canais (até oito), descreve os eventos e os modelos usados pelos eventos. Além disso, o manifesto de instrumentação permite a localização de cadeias de caracteres, para que você possa localizar as mensagens de rastreamento. O sistema de eventos e os consumidores de eventos podem usar os dados XML estruturados fornecidos no manifesto para executar consultas e análises.
Para obter informações sobre o manifesto de instrumentação, consulte Escrevendo um manifesto de instrumentação (Windows), EventManifest Schema (Windows) e Usando o log de eventos do Windows (Windows).
O manifesto de instrumentação a seguir mostra um fornecedor de eventos que utiliza o nome "Driver de exemplo". Observe que esse nome não precisa ser igual ao nome do binário do driver. O manifesto também especifica um GUID para o provedor e os caminhos para os arquivos de mensagem e recurso. Os arquivos de mensagem e recursos permitem que o ETW saiba onde localizar os recursos necessários para decodificar e relatar os eventos. Esses caminhos apontam para o local do arquivo do driver (.sys). O driver deve ser instalado no diretório especificado no computador de destino.
O exemplo usa o canal nomeado System, um canal para eventos do tipo Admin. Esse canal é definido no arquivo Winmeta.xml fornecido com o WDK (Windows Driver Kit) no diretório \include\um%WindowsSdkDir%. O canal System é protegido para aplicativos executados em contas de serviço do sistema. O manifesto inclui os modelos de evento que descrevem os tipos de dados fornecidos com os eventos quando eles são publicados, juntamente com seu conteúdo estático e dinâmico. Este manifesto de exemplo define três eventos: StartEvent, SampleEventAe UnloadEvent.
Além dos canais, você pode associar eventos a níveis e palavras-chave. Palavras-chave e níveis fornecem uma maneira de habilitar eventos e fornecer um mecanismo para filtrar eventos quando eles são publicados. As palavras-chave podem ser usadas para agrupar eventos logicamente relacionados. Um nível pode ser usado para indicar a gravidade ou a detalhamento de um evento, por exemplo, crítico, erro, aviso ou informativo. O arquivo Winmeta.xml contém valores predefinidos para atributos de evento.
Ao criar um modelo para a carga útil do evento (mensagem e dados do evento), você deve especificar os tipos de entrada e saída. Os tipos suportados são descritos na seção Comentários de InputType Complex Type (Windows).
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<instrumentationManifest
xmlns="http://schemas.microsoft.com/win/2004/08/events"
xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
>
<instrumentation>
<events>
<provider
guid="{b5a0bda9-50fe-4d0e-a83d-bae3f58c94d6}"
messageFileName="%SystemDrive%\ETWDriverSample\Eventdrv.sys"
name="Sample Driver"
resourceFileName="%SystemDrive%\ETWDriverSample\Eventdrv.sys"
symbol="DriverControlGuid"
>
<channels>
<importChannel
chid="SYSTEM"
name="System"
/>
</channels>
<templates>
<template tid="tid_load_template">
<data
inType="win:UInt16"
name="DeviceNameLength"
outType="xs:unsignedShort"
/>
<data
inType="win:UnicodeString"
name="name"
outType="xs:string"
/>
<data
inType="win:UInt32"
name="Status"
outType="xs:unsignedInt"
/>
</template>
<template tid="tid_unload_template">
<data
inType="win:Pointer"
name="DeviceObjPtr"
outType="win:HexInt64"
/>
</template>
</templates>
<events>
<event
channel="SYSTEM"
level="win:Informational"
message="$(string.StartEvent.EventMessage)"
opcode="win:Start"
symbol="StartEvent"
template="tid_load_template"
value="1"
/>
<event
channel="SYSTEM"
level="win:Informational"
message="$(string.SampleEventA.EventMessage)"
opcode="win:Info"
symbol="SampleEventA"
value="2"
/>
<event
channel="SYSTEM"
level="win:Informational"
message="$(string.UnloadEvent.EventMessage)"
opcode="win:Stop"
symbol="UnloadEvent"
template="tid_unload_template"
value="3"
/>
</events>
</provider>
</events>
</instrumentation>
<localization xmlns="http://schemas.microsoft.com/win/2004/08/events">
<resources culture="en-US">
<stringTable>
<string
id="StartEvent.EventMessage"
value="Driver Loaded"
/>
<string
id="SampleEventA.EventMessage"
value="IRP A Occurred"
/>
<string
id="UnloadEvent.EventMessage"
value="Driver Unloaded"
/>
</stringTable>
</resources>
</localization>
</instrumentationManifest>
3. Compile o manifesto de instrumentação usando o compilador de mensagens (Mc.exe)
O compilador de mensagens (Mc.exe) deve ser executado antes de compilar o código-fonte. O compilador de mensagens está incluído no Windows Driver Kit (WDK). O compilador de mensagens cria um arquivo de cabeçalho que contém definições para o provedor de eventos, atributos de eventos, canais e eventos. Você deve incluir esse arquivo de cabeçalho em seu código-fonte. O compilador de mensagens também coloca o script de compilador de recursos gerados (*.rc) e os arquivos de .bin gerados (recursos binários) que o script de compilador de recursos inclui.
Você pode incluir esta etapa como parte do seu processo de compilação de algumas maneiras:
Adicionar a tarefa do compilador de mensagens ao ficheiro de projeto do driver (conforme mostrado no exemplo do Eventdrv).
Usando o Visual Studio para adicionar o manifesto de instrumentação e configurar as propriedades do compilador de mensagens.
Adicionando uma tarefa de compilador de mensagens ao arquivo de projeto Para obter um exemplo de como você pode incluir o compilador de mensagens no processo de compilação, examine o arquivo de projeto para o de exemplo doEventdrv. No arquivo Eventdrv.vcxproj, há uma seção <MessageCompile> que chama o compilador de mensagens. O compilador de mensagens usa o arquivo de manifesto (evntdrv.xml) como entrada para gerar o arquivo de cabeçalho evntdrvEvents.h. Esta seção também especifica os caminhos para os arquivos RC gerados e habilita as macros de log do modo kernel. Você pode copiar esta seção e adicioná-la ao seu arquivo de projeto de driver (.vcxproj).
<MessageCompile Include="evntdrv.xml">
<GenerateKernelModeLoggingMacros>true</GenerateKernelModeLoggingMacros>
<HeaderFilePath>.\$(IntDir)</HeaderFilePath>
<GeneratedHeaderPath>true</GeneratedHeaderPath>
<WinmetaPath>"$(SDK_INC_PATH)\winmeta.xml"</WinmetaPath>
<RCFilePath>.\$(IntDir)</RCFilePath>
<GeneratedRCAndMessagesPath>true</GeneratedRCAndMessagesPath>
<GeneratedFilesBaseName>evntdrvEvents</GeneratedFilesBaseName>
<UseBaseNameOfInput>true</UseBaseNameOfInput>
</MessageCompile>
Quando você cria o exemplo de Eventdrv.sys, o Visual Studio cria os arquivos necessários para o rastreamento de eventos. Ele também adiciona o manifesto evntdrv.xml à lista de arquivos de recursos para o projeto de driver. Você pode selecionar e segurar (ou clicar com o botão direito do mouse) o manifesto para exibir as páginas de propriedades do Compilador de Mensagens.
Usando o Visual Studio para adicionar o manifesto de instrumentação
Você pode adicionar o manifesto de instrumentação ao projeto de driver e, em seguida, configurar as propriedades do compilador de mensagens para criar os arquivos de recurso e cabeçalho necessários.
Para adicionar o manifesto de instrumentação ao projeto usando o Visual Studio
No Gerenciador de Soluções, adicione o arquivo de manifesto ao projeto de driver. Selecione e segure (ou clique com o botão direito do mouse) Arquivos de Recursos > Adicionar > de Item Existente (por exemplo, evntdrv.xml ou mydriver.man).
Selecione e segure (ou clique com o botão direito do mouse) o arquivo que você acabou de adicionar e use as páginas de propriedades para alterar o tipo de item para MessageCompile e selecione Aplicar.
As propriedades do compilador de mensagens são exibidas. Em Configurações de geral, defina as seguintes opções e selecione Aplicar.
Geral Configurações Gerar macros de log do modo núcleo Sim (-km) Usar o nome base de entrada de Sim (-b) Em Opções de Arquivo, defina as seguintes opções e selecione Aplicar.
Opções de arquivo Configurações Gerar arquivo de cabeçalho para conter contador Sim caminho do arquivo de cabeçalho $(IntDir) Caminho dos Ficheiros de Mensagens Binárias e RC Gerados Sim Caminho do arquivo RC $(IntDir) Nome Base dos Ficheiros Gerados $(Nome do arquivo)
Por padrão, o compilador de mensagens usa o nome base do arquivo de entrada como o nome base dos arquivos que ele gera. Para especificar um nome base, defina o campo Nome Base dos Arquivos Gerados (-z). No exemplo de Eventdr.sys, o nome base é definido como evntdrvEvents para que corresponda ao nome do arquivo de cabeçalho evntdrvEvents.h, que está incluído em evntdrv.c.
Observação
Se você não incluir o arquivo .rc gerado em seu projeto do Visual Studio, você pode receber mensagens de erro sobre recursos não encontrados quando você instala o arquivo de manifesto.
4. Adicione o código gerado para gerar (publicar) os eventos (registrar, cancelar o registro e gravar eventos)
No manifesto de instrumentação, você definiu os nomes do provedor de eventos e os descritores de eventos. Quando você compila o manifesto de instrumentação com o compilador de mensagens, o compilador de mensagens gera um arquivo de cabeçalho que descreve os recursos e também define macros para os eventos. Agora, você deve adicionar o código gerado ao seu driver para gerar esses eventos.
No arquivo de origem, inclua o arquivo de cabeçalho de evento produzido pelo compilador de mensagens (MC.exe). Por exemplo, na amostra doEventdrv, o ficheiro fonte Evntdrv.c inclui o ficheiro de cabeçalho (evntdrvEvents.h) que foi gerado no passo anterior:
#include "evntdrvEvents.h"Adicione as macros que registrem e desregistrem o driver como um fornecedor de eventos. Por exemplo, no ficheiro de cabeçalho do exemplo Eventdrv (evntdrvEvents.h), o compilador de mensagens cria macros com base no nome do provedor. No manifesto, o exemplo Eventdrv usa o nome "Driver de Exemplo" como o nome do provedor. O compilador de mensagens combina o nome do provedor com a macro de evento para registrar o provedor, neste caso, EventRegisterSample_Driver.
// This is the generated header file envtdrvEvents.h // // ... // // // Register with ETW Vista + // #ifndef EventRegisterSample_Driver #define EventRegisterSample_Driver() McGenEventRegister(&DriverControlGuid, McGenControlCallbackV2, &DriverControlGuid_Context, &Sample_DriverHandle) #endifAdicione o macro EventRegister<provider> à sua função DriverEntry. Adicione essa função após o código que cria e inicializa o objeto de dispositivo. Observe que deve corresponder a chamada para a função EventRegister do provedor<> com uma chamada para EventUnregister do provedor<>. Você pode cancelar o registro do motorista na rotina de Descarga* do motorista.
// DriverEntry function // ... // Register with ETW // EventRegisterSample_Driver();Adicione o código gerado aos arquivos de origem do driver para gravar (aumentar) os eventos especificados no manifesto. O arquivo de cabeçalho compilado a partir do manifesto contém o código gerado para o driver. Use o EventWrite<funções de> de eventos definidas no arquivo de cabeçalho para publicar mensagens de rastreamento no ETW. Por exemplo, o código a seguir mostra as macros para eventos definidos em evntdrvEvents.h para o exemplo Eventdrv.
As macros para escrever esses eventos são chamadas:
EventWriteStartEvent,EventWriteSampleEventAeEventWriteUnloadEvent. Como você pode ver na definição dessas macros, a definição de macro inclui automaticamente um evento EventEnabled<> macro que verifica se o evento está habilitado. A verificação elimina a necessidade de construir o payload se o evento não estiver ativo./// // This is the generated header file envtdrvEvents.h // // ... // // Enablement check macro for StartEvent // #define EventEnabledStartEvent() ((Sample_DriverEnableBits[0] & 0x00000001) != 0) // // Event Macro for StartEvent // #define EventWriteStartEvent(Activity, DeviceNameLength, name, Status)\ EventEnabledStartEvent() ?\ Template_hzq(Sample_DriverHandle, &StartEvent, Activity, DeviceNameLength, name, Status)\ : STATUS_SUCCESS\ // // Enablement check macro for SampleEventA // #define EventEnabledSampleEventA() ((Sample_DriverEnableBits[0] & 0x00000001) != 0) // // Event Macro for SampleEventA // #define EventWriteSampleEventA(Activity)\ EventEnabledSampleEventA() ?\ TemplateEventDescriptor(Sample_DriverHandle, &SampleEventA, Activity)\ : STATUS_SUCCESS\ // // Enablement check macro for UnloadEvent // #define EventEnabledUnloadEvent() ((Sample_DriverEnableBits[0] & 0x00000001) != 0) // // Event Macro for UnloadEvent // #define EventWriteUnloadEvent(Activity, DeviceObjPtr)\ EventEnabledUnloadEvent() ?\ Template_p(Sample_DriverHandle, &UnloadEvent, Activity, DeviceObjPtr)\ : STATUS_SUCCESS\Adicione as macros de eventos EventWrite<> ao seu código-fonte para os eventos que está a levantar. Por exemplo, o trecho de código a seguir mostra a rotina de DriverEntrydo exemplo Eventdrv. O DriverEntry inclui as macros para registar o driver com ETW (EventRegisterSample_Driver) e a macro para gravar o evento do driver para ETW (EventWriteStartEvent).
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: DriverObject - pointer to the driver object RegistryPath - pointer to a unicode string representing the path to driver-specific key in the registry Return Value: STATUS_SUCCESS if successful STATUS_UNSUCCESSFUL otherwise --*/ { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING LinkName; PDEVICE_OBJECT EventDrvDeviceObject; WCHAR DeviceNameString[128]; ULONG LengthToCopy = 128 * sizeof(WCHAR); UNREFERENCED_PARAMETER (RegistryPath); KdPrint(("EventDrv: DriverEntry\n")); // // Create Dispatch Entry Points. // DriverObject->DriverUnload = EventDrvDriverUnload; DriverObject->MajorFunction[ IRP_MJ_CREATE ] = EventDrvDispatchOpenClose; DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = EventDrvDispatchOpenClose; DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = EventDrvDispatchDeviceControl; RtlInitUnicodeString( &DeviceName, EventDrv_NT_DEVICE_NAME ); // // Create the Device object // Status = IoCreateDevice( DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &EventDrvDeviceObject); if (!NT_SUCCESS(Status)) { return Status; } RtlInitUnicodeString( &LinkName, EventDrv_WIN32_DEVICE_NAME ); Status = IoCreateSymbolicLink( &LinkName, &DeviceName ); if ( !NT_SUCCESS( Status )) { IoDeleteDevice( EventDrvDeviceObject ); return Status; } // // Choose a buffering mechanism // EventDrvDeviceObject->Flags |= DO_BUFFERED_IO; // // Register with ETW // EventRegisterSample_Driver(); // // Log an Event with : DeviceNameLength // DeviceName // Status // // Copy the device name into the WCHAR local buffer in order // to place a NULL character at the end, since this field is // defined in the manifest as a NULL-terminated string if (DeviceName.Length <= 128 * sizeof(WCHAR)) { LengthToCopy = DeviceName.Length; } RtlCopyMemory(DeviceNameString, DeviceName.Buffer, LengthToCopy); DeviceNameString[LengthToCopy/sizeof(WCHAR)] = L'\0'; EventWriteStartEvent(NULL, DeviceName.Length, DeviceNameString, Status); return STATUS_SUCCESS; }
Adicione todas as macros de eventos<EventWrite> ao seu código-fonte para os eventos que está gerando. Você pode examinar o exemplo Eventdrv para ver como as outras duas macros são chamadas para os eventos no código-fonte do driver.
Cancele o registro do driver como um provedor de eventos usando a macro EventUnregister<provedor> do arquivo de cabeçalho gerado.
Coloque esta chamada de função na sua rotina de descarregamento do driver. Nenhuma chamada de rastreamento deve ser feita após a macro EventUnregister<fornecedor> ser chamada. A falha ao anular o registo do fornecedor de eventos pode causar erros quando o processo é descarregado, pois quaisquer funções de retorno de chamada associadas ao processo deixam de ser válidas.
// DriverUnload function // ... // // Unregister the driver as an ETW provider // EventUnregisterSample_Driver();
5. Construa o driver
Se você adicionou o manifesto do instrumento ao projeto e configurou as propriedades do compilador de mensagens (MC.exe), você pode criar o projeto de driver ou solução usando Visual Studio e MSBuild.
Abra a solução de driver no Visual Studio.
Crie o exemplo a partir do menu Compilar selecionando Build Solution. Para obter mais informações sobre como criar soluções, consulte Criando um driver.
6. Instale o manifesto
Você deve instalar o manifesto no sistema de destino para que os consumidores de eventos (por exemplo, o Log de Eventos) possam encontrar o local do binário que contém os metadados do evento. Se você adicionou a tarefa de compilador de mensagem ao projeto de driver na Etapa 3, o manifesto de instrumentação foi compilado e os arquivos de recurso foram gerados quando você criou o driver. Use o Utilitário de linha de comando de eventos do Windows (Wevtutil.exe) para instalar o manifesto. A sintaxe para instalar o manifesto é a seguinte:
wevtutil.exe imdrivermanifest
Por exemplo, para instalar o manifesto para o driver de exemplo Evntdrv.sys, abra uma janela de prompt de comando com privilégios elevados (Executar como administrador) navegue até o diretório onde o arquivo evntdrv.xml está localizado e digite o seguinte comando:
Wevtutil.exe im evntdrv.xml
Quando a sessão de rastreamento estiver concluída, desinstale o manifesto usando a sintaxe a seguir.
wevtutil.exe umdrivermanifest
Por exemplo, para desinstalar o manifesto do exemplo de Eventdrv :
Wevtutil.exe um evntdrv.xml
7. Teste o driver para verificar o suporte ETW
Instale o driver. Aplique o driver para gerar atividade de rastreamento. Veja os resultados no Visualizador de Eventos. Você também pode executar Traceloge, em seguida, executar Tracerpt, uma ferramenta para processar logs de rastreamento de eventos, para controlar, coletar e exibir os logs de rastreamento de eventos.