class KTrace, class KDebugOnlyTrace:
【Overview】
类KTrace提供了一种向调试器或Monitor工具输出调试内容的方法。这个类既支持对于integers, ASCII strings, 和Unicode strings等数据格式的printf方式的输出,也支持某些类型的C++的输出流方式的输出,待输出的数据将被缓冲,直到被输出到Monitor。
类KDebugOnlyTrace和KTrace的工作基本相同,不同在于:当预处理符号DBG被定义为0的时候,它将产生最简短的代码。
【Channels】
每个KTrace对象将由一个特殊的通道连接到Monitor。这个通道是一个独特的字节流通道,只能使用能够映射到ANSI字符上的那些符号。DBGMSG在初始化的时候创建了一个默认的通道,KTrace类在定义的时候如果在响应的通道参数上写NULL,那么它使用的就是这个默认通道。否则就是重建一个新的通道。
通道有两种:非中断通道和中断通道。当处理器中断过程中需要用Trace输出信息时,必须使用中断通道,比如在IRQL > DISPATCH_LEVEL的级别上。所有在中断通道上的操作都是在极高的中断级上完成的,目的是为了保证正确的输出次序(即Trace不会被中断)。构造一个中断通道时需要一个指向中断对象的指针作为参数。(请注意:如果默认的通道被用于跟踪IRQL > DISPATCH_LEVEL级别上的调试信息,那么在KTrace构造函数中就不需要中断对象了。此时默认通道使用的时DbgPrint服务,使它即使在ISR中断服务程序中执行也是安全的)。
【Levels】
除了通道,每个KTrace对象还有一个输出级,断点级和目标掩码。
调用者在输出时,会包含一个参数来指定输出信息的优先级。如果这个数值大于等于这个对象的输出阈值,数据才能被输出。方法SetOutputLevel可以设置KTrace对象的输出阈值。
类似的,当包含的优先级的值大于等于对象断点级的阈值,它就会调用DbgBreakPoint来产生一个断点。方法SetBreakLevel可以设置KTrace对象的断点级阈值。
最后,目标掩码控制输出的对象,或者输出到调试器(Windbg或SoftICE),或者输出到Monitor。方法SetTarget可以设置KTrace的输出设备掩码。
【成员函数介绍】
1、构造函数KTrace:
KTrace(
PCHAR prefix = NULL, //由Trace输出的数据前缀,每次输出前都先输出的东西
ULONG targetmask = TRACE_DEBUGGER|TRACE_MONITOR, //输出的目标设备,默认是两者都输出
TRACE_LEVEL outputlevel = TraceAlways, //输出级别阈值, TraceAlways是最高级别
BREAK_LEVEL breaklevel = BreakNever, //断点级别遇值,BreakNever是最低级别
PUNICODE_STRING channel = NULL,//输出通道,Unicode string 或 KUstring,有默认通道
PKINTERRUPT intobject = NULL //中断对象,system interrupt object的地址或KInterrupt实例 //默认是非中断通道
);
KTrace(
PUNICODE_STRING prefix, //前缀是UNICODE_STRING,则要明确写入参数值
ULONG targetmask = TRACE_DEBUGGER|TRACE_MONITOR,
TRACE_LEVEL outputlevel = TraceAlways,
BREAK_LEVEL breaklevel = BreakNever,
PUNICODE_STRING channel = NULL,
PKINTERRUPT intobject = NULL
);
2、三个Set方法
VOID SetTarget( ULONG targetmask ); //设置输出目标
VOID SetOutputLevel( TRACE_LEVEL newOutputLevel ); //设置输出级别阈值
VOID SetBreakLevel( BREAK_LEVEL newBreakLevel ); //设置断点级别阈值
3、重载operator <<
KTrace& operator << (const char* string);
KTrace& operator << (const PWSTR string);
KTrace& operator << (const PUNICODE_STRING string);
KTrace& operator << (const char charval);
KTrace& operator << (const ULONG uintval);
KTrace& operator << (const USHORT uintval);
KTrace& operator << (const UCHAR uintval);
KTrace& operator << (TRACE_LEVEL level);
KTrace& operator << (TRACE_RADIX radix);
KTrace& operator << (const KIrp I);
KTrace& operator << (const ULONG_PTR A64BitValue);
共有11中重载方式,需要注意:
(1)重载<<的是KTrace对象,而不是指针,所以用<<的时候如果用的是指针,则要通过指针找到它指向的对象,然后再输出。例如:
KTrace* Tracer = new (NonPagedPool) KTrace("MyDriver");
*Tracer << "tracing enabled/n"; //这里的*Tracer就是找到了对象
(2)上例KTrace中包含了前缀,每输出一行都要输出前缀,但是在一次输出中包含"/n"并不会导致前缀重复输出。
(3)在x86平台上,输出ULONG_PTR类型等价于输出ULONG类型,可以是一个ULONG_PTR类型的数字,也可以是任何一个普通的地址(比如PVOID),输出格式是十六进制。
4、类似C风格输出的Trace方法
VOID Trace(
TRACE_LEVEL level, //选择输出级别
PCHAR format, //类似于printf的格式化输出变量方式
. . . //若干个变量
);
输出级别是Trace方法指定的(大于等于阈值才输出),断点级别是沿用KTrace构造时或最近一次设置的值(大于等于阈值就会调用
DbgBreakPoint断点服务)。%S可以用于没有结束符的Unicode string,扩大格式的string不能超过256字节。
----------------
§ 译自"DriverWorks帮助文件" §
§ 李文凯 2008年03月19日 §
----------------