Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Bagian ini menjelaskan cara menggunakan API mode kernel Pelacakan Peristiwa untuk Windows (ETW) untuk menambahkan pelacakan peristiwa ke driver mode kernel. API mode kernel ETW diperkenalkan dengan Windows Vista dan tidak didukung di sistem operasi sebelumnya. Gunakan WPP Software Tracing atau WMI Event Tracing jika driver Anda perlu mendukung kemampuan pelacakan di Windows 2000 dan yang lebih baru.
Petunjuk / Saran
Untuk melihat kode sampel yang menunjukkan cara menerapkan ETW menggunakan Windows Driver Kit (WDK) dan Visual Studio, lihat sampel Eventdrv.
Di bagian ini:
Alur Kerja - Menambahkan Pelacakan Peristiwa ke Driver Kernel-Mode
1. Tentukan jenis acara yang akan diangkat dan tempat untuk menerbitkannya
2. Membuat manifes instrumentasi yang menentukan penyedia, peristiwa, dan saluran
3. Mengkompilasi manifes instrumentasi dengan menggunakan pengkompilasi pesan (Mc.exe)
7. Uji driver untuk memverifikasi dukungan ETW
Alur Kerja - Menambahkan Pelacakan Peristiwa ke Driver Kernel-Mode
1. Tentukan jenis peristiwa yang akan dinaikkan dan tempat menerbitkannya
Sebelum mulai mengoding, Anda harus memutuskan jenis peristiwa apa yang Anda inginkan untuk dicatat driver melalui Pelacakan Peristiwa untuk Windows (ETW). Misalnya, Anda mungkin ingin mencatat peristiwa yang dapat membantu Anda mendiagnosis masalah setelah driver didistribusikan, atau peristiwa yang mungkin membantu Anda saat mengembangkan driver Anda. Untuk informasi, lihat Referensi Log Peristiwa Windows.
Jenis peristiwa diidentifikasi dengan saluran. Saluran adalah aliran peristiwa dengan nama khusus yang mencakup tipe Admin, Operasional, Analitik, atau Debug dan diarahkan kepada audiens tertentu, mirip dengan saluran televisi. Saluran mengirimkan peristiwa dari penyedia peristiwa ke log peristiwa dan konsumen peristiwa. Untuk informasi lebih lanjut, lihat Menentukan Saluran.
Selama pengembangan, Anda kemungkinan besar tertarik untuk melacak peristiwa yang membantu Anda men-debug kode Anda. Saluran yang sama ini dapat digunakan dalam kode produksi untuk membantu memecahkan masalah yang mungkin muncul setelah driver disebarkan. Anda mungkin juga ingin melacak peristiwa yang dapat digunakan untuk mengukur performa; peristiwa ini dapat membantu profesional TI menyempurnakan performa server dan dapat membantu mengidentifikasi penyempitan jaringan.
2. Buat manifes instrumentasi yang mendefinisikan penyedia, peristiwa, dan saluran
Manifes instrumentasi adalah file XML yang memberikan deskripsi formal tentang peristiwa yang akan dikemukakan oleh penyedia. Manifes instrumentasi mengidentifikasi penyedia peristiwa, menentukan saluran atau saluran (hingga delapan), dan menjelaskan peristiwa, dan templat yang digunakan peristiwa. Selain itu, manifes instrumentasi memungkinkan pelokalan string, sehingga Anda dapat melokalisasi pesan jejak. Sistem peristiwa dan konsumen peristiwa dapat menggunakan data XML terstruktur yang disediakan dalam manifes untuk melakukan kueri dan analisis.
Untuk informasi tentang manifes instrumentasi, lihat Menulis Manifes Instrumentasi (Windows), EventManifest Schema (Windows) dan Menggunakan Log Peristiwa Windows (Windows).
Berikut merupakan manifes instrumentasi yang menunjukkan penyedia acara yang menggunakan nama "Sample Driver." Catatan: nama ini tidak harus sama dengan nama biner driver. Manifes juga menentukan GUID untuk penyedia dan jalur ke file pesan dan sumber daya. File pesan dan sumber daya memberi tahu ETW di mana menemukan sumber daya yang diperlukan untuk mendekode dan melaporkan peristiwa. Jalur ini menunjuk ke lokasi file driver (.sys). Pengandar harus diinstal dalam direktori yang ditentukan pada komputer target.
Contoh menggunakan saluran bernama System, saluran untuk peristiwa jenis Admin. Saluran ini didefinisikan dalam file Winmeta.xml yang disediakan dengan Windows Driver Kit (WDK) di direktori%WindowsSdkDir%\include\um. Saluran Sistem diamankan untuk aplikasi yang berjalan di bawah akun layanan sistem. Manifes mencakup templat acara yang menjelaskan jenis data yang disediakan bersama acara saat diterbitkan, beserta konten statis dan dinamisnya. Contoh manifes ini mendefinisikan tiga peristiwa: StartEvent, SampleEventA, dan UnloadEvent.
Selain saluran, Anda dapat mengaitkan peristiwa dengan tingkat dan kata kunci. Kata kunci dan tingkat menyediakan cara untuk mengaktifkan peristiwa dan menyediakan mekanisme untuk memfilter peristiwa saat dipublikasikan. Kata kunci dapat digunakan untuk mengelompokkan peristiwa terkait logis bersama-sama. Tingkat dapat digunakan untuk menunjukkan tingkat keparahan atau verbositas peristiwa, misalnya, kritis, kesalahan, peringatan, atau informasi. File Winmeta.xml berisi nilai yang telah ditentukan sebelumnya untuk atribut peristiwa.
Saat Anda membuat templat untuk payload peristiwa (pesan peristiwa, dan data), Anda harus menentukan jenis input dan output. Jenis yang didukung diuraikan dalam bagian Keterangan dari Tipe Kompleks InputType (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. Kompilasi manifes instrumentasi dengan menggunakan pengkompilasi pesan (Mc.exe)
Pengkompilasi pesan (Mc.exe) harus dijalankan sebelum Anda mengkompilasi kode sumber Anda. Pengkompilasi pesan disertakan dalam Windows Driver Kit (WDK). Pengkompilasi pesan membuat file header yang berisi definisi untuk penyedia peristiwa, atribut peristiwa, saluran, dan peristiwa. Anda harus menyertakan file header ini dalam kode sumber Anda. Pengkompilasi pesan juga menempatkan skrip pengkompilasi sumber daya yang dihasilkan (*.rc) dan file .bin yang dihasilkan (sumber daya biner) yang disertakan oleh skrip pengkompilasi sumber daya.
Anda dapat menyertakan langkah ini sebagai bagian dari proses build Anda dalam beberapa cara:
Menambahkan tugas pengkompilasi pesan ke file proyek driver (seperti yang ditunjukkan dalam sampel Eventdrv).
Menggunakan Visual Studio untuk menambahkan manifes instrumentasi dan untuk mengonfigurasi properti Pengkompilasi Pesan.
Menambahkan tugas pengkompilasi pesan ke file proyek Untuk contoh bagaimana Anda dapat menyertakan pengkompilasi pesan dalam proses build, lihat file proyek untuk sampel Eventdrv. Dalam file Eventdrv.vcxproj, ada bagian <> MessageCompile yang memanggil pengkompilasi pesan. Pengkompilasi pesan menggunakan file manifes (evntdrv.xml) sebagai input untuk menghasilkan file header evntdrvEvents.h. Bagian ini juga menentukan jalur untuk file RC yang dihasilkan dan mengaktifkan makro pengelogan mode kernel. Anda dapat menyalin bagian ini dan menambahkannya ke file proyek driver Anda (.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>
Saat Anda membuat sampel Eventdrv.sys, Visual Studio membuat file yang diperlukan untuk pelacakan peristiwa. Ini juga menambahkan manifes evntdrv.xml ke daftar File Sumber Daya untuk proyek driver. Anda dapat memilih dan menahan (atau mengklik kanan) manifes untuk melihat halaman properti Pengkompilasi Pesan.
Menggunakan Visual Studio untuk menambahkan manifes instrumentasi
Anda dapat menambahkan manifes instrumentasi ke proyek driver lalu mengonfigurasi properti pengkompilasi pesan untuk membangun file sumber daya dan header yang diperlukan.
Untuk menambahkan manifes instrumentasi ke proyek menggunakan Visual Studio
Di Penjelajah Solusi, tambahkan file manifes ke proyek driver. Pilih dan tahan (atau klik kanan) File Sumber Daya > Tambahkan > Item yang Ada (misalnya, evntdrv.xml atau mydriver.man).
Pilih dan tahan (atau klik kanan) file yang baru saja Anda tambahkan dan gunakan halaman properti untuk mengubah jenis item menjadi MessageCompile dan pilih Terapkan.
Properti Pengkompilasi Pesan muncul. Di bawah pengaturan Umum, atur opsi berikut lalu pilih Terapkan.
Umum Pengaturan Buat Makro Pencatatan Mode Kernel Ya (-km) Gunakan Nama Dasar dari Input Ya (-b) Di bawah opsi file , atur opsi berikut lalu pilih Terapkan.
Opsi File Pengaturan Menghasilkan file header yang berisi penghitung Ya Jalur File Header $(IntDir) Jalur File Pesan RC dan Biner yang Dihasilkan Ya Jalur File RC $(IntDir) Nama Dasar File yang Dihasilkan $(Nama File)
Secara default, pengkompilasi pesan menggunakan nama dasar file input sebagai nama dasar file yang dihasilkannya. Untuk menentukan nama dasar, tetapkan bidang Nama Dasar File yang Dihasilkan (-z). Dalam sampel Eventdr.sys, nama dasar diatur ke evntdrvEvents sehingga cocok dengan nama file header evntdrvEvents.h, yang disertakan dalam evntdrv.c.
Nota
Jika Anda tidak menyertakan file .rc yang dihasilkan dalam proyek Visual Studio, Anda mungkin mendapatkan pesan kesalahan tentang sumber daya yang tidak ditemukan saat menginstal file manifes.
4. Tambahkan kode yang dihasilkan untuk menaikkan (menerbitkan) peristiwa (daftar, membatalkan pendaftaran, dan menulis peristiwa)
Dalam manifes instrumentasi, Anda menentukan nama penyedia peristiwa dan deskriptor peristiwa. Saat Anda mengkompilasi manifes instrumentasi dengan pengkompilasi pesan, pengkompilasi pesan menghasilkan file header yang menjelaskan sumber daya dan juga menentukan makro untuk peristiwa tersebut. Sekarang, Anda harus menambahkan kode yang dihasilkan ke driver Anda untuk memicu peristiwa ini.
Dalam file sumber Anda, sertakan file header peristiwa yang dihasilkan oleh pengkompilasi pesan (MC.exe). Misalnya, dalam sampel Eventdrv, file sumber Evntdrv.c menyertakan file header (evntdrvEvents.h) yang dihasilkan pada langkah sebelumnya:
#include "evntdrvEvents.h"Tambahkan makro yang melakukan pendaftaran dan pembatalan pendaftaran driver sebagai penyedia kejadian. Misalnya, dalam file header untuk sampel Eventdrv (evntdrvEvents.h), pengkompilasi pesan membuat makro berdasarkan nama penyedia. Dalam manifes, sampel Eventdrv menggunakan nama "Sample Driver" sebagai nama penyedia. Pengompilasi pesan menggabungkan nama penyedia dengan makro peristiwa untuk mendaftarkan penyedia, dalam hal ini, 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) #endifTambahkan makro EventRegister<penyedia> ke dalam fungsi DriverEntry Anda. Tambahkan fungsi ini setelah kode yang membuat dan menginisialisasi objek perangkat. Perhatikan bahwa Anda harus mencocokkan panggilan ke fungsi EventRegister<penyedia> dengan panggilan ke fungsi EventUnregister<penyedia>. Anda dapat menghapus pendaftaran driver di rutinitas Unload* driver Anda.
// DriverEntry function // ... // Register with ETW // EventRegisterSample_Driver();Tambahkan kode yang dihasilkan ke file sumber driver Anda untuk menulis (menaikkan) peristiwa yang Anda tentukan dalam manifes. File header yang Anda kompilasi dari manifes berisi kode yang dihasilkan untuk driver. Gunakan fungsi EventWrite <> yang didefinisikan dalam file header untuk menerbitkan pesan trace ke ETW. Misalnya, kode berikut menunjukkan makro untuk peristiwa yang ditentukan dalam evntdrvEvents.h untuk sampel Eventdrv.
Makro untuk menulis peristiwa ini disebut:
EventWriteStartEvent,EventWriteSampleEventA, danEventWriteUnloadEvent. Seperti yang Anda lihat dalam definisi makro ini, definisi makro secara otomatis menyertakan makro EventEnabled<peristiwa> yang memeriksa apakah peristiwa diaktifkan. Periksa menghilangkan keperluan untuk membangun payload jika event tidak diaktifkan./// // 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\Tambahkan makro acara <EventWrite> ke dalam kode sumber Anda untuk acara yang Anda picu. Misalnya, cuplikan kode berikut menunjukkan rutinitas DriverEntry dari sampel Eventdrv. DriverEntry menyertakan makro untuk mendaftarkan driver dengan ETW (EventRegisterSample_Driver) dan makro untuk menulis peristiwa driver ke 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; }
Tambahkan semua makro peristiwa EventWrite<> ke dalam kode sumber Anda untuk menangani peristiwa yang Anda bangkitkan. Anda dapat memeriksa sampel Eventdrv untuk melihat bagaimana dua makro lainnya dipanggil untuk peristiwa dalam kode sumber driver.
Batalkan pendaftaran driver sebagai penyedia event menggunakan makro EventUnregister <> dari file header yang dihasilkan.
Lakukan panggilan fungsi ini dalam rutinitas pembongkaran driver Anda. Tidak ada panggilan pelacakan yang harus dilakukan setelah makro penyedia EventUnregister<> dipanggil. Kegagalan untuk membatalkan pendaftaran penyedia acara dapat menyebabkan error ketika proses dihentikan karena fungsi callback apa pun yang terkait dengan proses tersebut tidak lagi valid.
// DriverUnload function // ... // // Unregister the driver as an ETW provider // EventUnregisterSample_Driver();
5. Membangun driver
Jika Anda telah menambahkan manifes instrumen ke proyek dan telah mengonfigurasi properti pengkompilasi pesan (MC.exe), Anda dapat membangun proyek atau solusi driver menggunakan Visual Studio dan MSBuild.
Buka solusi driver di Visual Studio.
Buat sampel dari menu Build dengan memilih Build Solution. Untuk informasi selengkapnya tentang membangun solusi, lihat Membangun Driver.
6. Instalasi manifes
Anda harus menginstal manifes pada sistem target sehingga konsumen peristiwa (misalnya, Log Peristiwa) dapat menemukan lokasi biner yang berisi metadata peristiwa. Jika Anda menambahkan tugas pengkompilasi pesan ke proyek driver di Langkah 3, manifes instrumentasi dikompilasi dan file sumber daya dibuat saat Anda membuat driver. Gunakan Utilitas Baris Perintah Peristiwa Windows (Wevtutil.exe) untuk menginstal manifes. Sintaks untuk menginstal manifes adalah sebagai berikut:
wevtutil.exedrivermanifest
Misalnya, untuk menginstal manifes untuk driver sampel Evntdrv.sys, buka jendela Prompt Perintah dengan hak istimewa yang ditinggikan (Jalankan sebagai administrator) navigasikan ke direktori tempat file evntdrv.xml berada dan masukkan perintah berikut:
Wevtutil.exe im evntdrv.xml
Saat sesi pelacakan Anda selesai, hapus instalan manifes menggunakan sintaks berikut.
wevtutil.exe ehmdrivermanifest
Misalnya, untuk menghapus instalan manifes untuk sampel Eventdrv:
Wevtutil.exe um evntdrv.xml
7. Uji driver untuk memverifikasi dukungan ETW
Pasang driver. Jalankan driver untuk menghasilkan aktivitas pelacakan. Lihat hasilnya di Penampil Peristiwa. Anda juga dapat menjalankan Tracelog, lalu menjalankan Tracerpt, alat untuk memproses log jejak peristiwa, untuk mengontrol, mengumpulkan, dan melihat log jejak peristiwa.