6、驱动中注意的要点
1:CE下同名设备不能大于10
CE5.0中已经没有这个问题了,以前的版本可以这样做:只给上层输出一个设备,然后用一个IOCTL去打开一个个的物理设备这样就可以做到不受任何限制了。
2:MDD与PDD
一个驱动程序通常会被分成硬件相关(PDD)与硬件无关(MDD)层两部分。
当然,这种分层不是必须的,只是采用这种分层以后可以少写很多代码,因为微软提供了很多驱动程序的MDD。即使CE中没有我们所写的驱动程序的样例,采用这种结构以后,当需要写第二个程序时,就可以重用它的代码,就可以提高开发效率。
MDD是提供同类型的设备(比如串口)都会有的功能,这样PDD基本上就只有寄存器操作了。
像串口的中断处理,Read/Write函数,其大部分代码都是在MDD中实现的,不同的串口实现中只需要提供一些实际操作寄存器的函数。不同的驱动程序,其MDD与PDD的接口不尽相同,
3:XXX_Init函数的返回句柄
通常,这个句柄是驱动程序自己保存数据的一个指针,我们在Init返回时告诉上层程序,以后上层调用其它函数(例如Open)时,会将这个值传入,这样,我们就可以访问自己的一些私有数据。
当然,也可以返回一个任意的非0值对于一个设备驱动程序,系统不用的层会有不同的句柄。我们在XXX_Init中返回的句柄保存在设备管理器中,别的程序中应该是看不到的,而用CreateFile也会得到一个文件句柄,这个保存在哪我不知道,但和前者是不一样的。也就是说不同层的软件所关心的句柄也会不一样
4:DEBUGMSG与RETAILMSG的区别
它们都是输出调试信息用的,区别是:
DEBUGMSG只在DEBUG版中有效,RELEASE版中它被定义成了NULL
RETAILMSG在DEBUG和RELEASE版中都可以输出,
而且DEBUGMSG可以在运行时刻用DEBUZONE控制要不要输出信息。
在ship build 时,RETAILMSG 和DEBUGMSG都无效。
5:调试区与dpCurSettings
我们都是利用OutpubDebugString函数来实现调试信息的输出的,但是由于系统底层的调试信息非常繁多,如果这样大量的调试信息用于实时输出的话一定会影响到系统的性能和实时性,也就影响到了系统的运行。如果有一种方式能允许开发人员自己选择输出哪些调试信息,不输出哪些调试信息的话,那么就可以让开发人员只看到关心的调试信息,而把诸如键盘按键、鼠标移动等无用的调试信息隐去,则可以更好的提高开发效率。
调试区就是为了解决以上提出的问题的,对某一个驱动程序,它规定好自己向外输出的调试信息的分类,比如初始化时的信息,出错时的信息,释放时的信息,激活时的信息等,然后分成几个调试区,在现有的CE版本中最多允许16个调试区。
开发人员通过Platform Builder中Target菜单下的CE Debug Zones命令来决定想要得到哪一个或哪几个调试区的信息,在驱动程序中则可以根据开发人员的选择来输出指定调试区的信息。这就是调试区大体上的工作原理。
调试区的定义,声明,注册及使用。
在程序中使用调试区之前必须先定义它们,一个程序的16个调试区编号分别为0-15。代码样例如下所示:
#ifdef DEBUG
//
// For debug builds, use the real zones.
//
#define ZONE_TEST DEBUGZONE(0)
#define ZONE_PARAMS DEBUGZONE(1)
#define ZONE_VERBOSE DEBUGZONE(2)
……
#define ZONE_WARN DEBUGZONE(14)
#define ZONE_ERROR DEBUGZONE(15)
#else
//
// For retail builds, use forced messages based on the zones turned on below.
//
#define ZONE_TEST 0
#define ZONE_PARAMS 0
#define ZONE_VERBOSE 0
……
#define ZONE_WARN 0
#define ZONE_ERROR 0
#endif
这样,就可以程序的DEBUG版本中使用调试区了,而在RELEASE版本中则将其全部定义为0,调试信息即不再输出。
在程序中,除了以上的定义以外,还要声明几个专用的调试信息输出函数,这些函数与OutputDebugString函数的区别就在于在调用时需要指定对应的调试区,这些函数以及以上用到的DEBUGZONE宏的定义都在DbgApi.h头文件中,因此只要在源程序中包含此头文件即可。除此以外,还需要一个全局的DEBPARAM类型的变量命名为dpCurSettings,以供集成开发环境和调试信息输出函数使用。其代码样例如下:
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("WaveDriver"), {
TEXT("Test") // 0
,TEXT("Params") // 1
,TEXT("Verbose") // 2
,TEXT("Interrupt") // 3
,TEXT("WODM") // 4
,TEXT("WIDM") // 5
,TEXT("PDD") // 6
,TEXT("MDD") // 7
,TEXT("Regs") // 8
,TEXT("Misc") // 9
,TEXT("Init") // 10
,TEXT("IOcontrol") // 11
,TEXT("Alloc") // 12
,TEXT("Function") // 13
,TEXT("Warning") // 14
,TEXT("Error") // 15
}
,
(1 << 15) // Errors
| (1 << 14) // Warnings
};
#endif
此例中还把ERROR和WARN调试区作为默认被开发人员选中的调试区。
要想使用调试区,还需要做的最后一件准备的事情就是在程序中进行注册,也就是在程序启动时通知集成开发环境本程序中要使用调试区,这个注册很简单,只要在程序的入口处使用DEBUGREGISTER宏即可,样例如下:
DllEntry (
HANDLE hinstDLL,
DWORD Op,
LPVOID lpvReserved
)
{
switch (Op) {
case DLL_PROCESS_ATTACH :
DEBUGREGISTER((HINSTANCE)hinstDLL);
break;
……