现在的位置: 首页 > 综合 > 正文

WDM驱动程序开发之调试信息输出篇:KTrace, KDebugOnlyTrace类

2013年11月25日 ⁄ 综合 ⁄ 共 3145字 ⁄ 字号 评论关闭

 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日    §
                                            ----------------

【上篇】
【下篇】

抱歉!评论已关闭.