Windows Driver开发_TraceEvents调试以及加载驱动的方法
在最新版的WDK框架里,我们新建了Windows Driver KMDF模型之后默认使用的TraceEvents来打印输出的,这套输出机制叫WPP,我们可以在DriverEntry函数里看到它的初始化代码:
WPP_INIT_TRACING(DriverObject, RegistryPath);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
如果想要使用TraceEvents需要在WPP_INIT_TRACING之后才能使用,它们依赖于Trace.h文件,一般默认生成KMDF时Visual Studio会自动生成这个头文件,里面包含了WPP的相关定义。
如果没有可以新建一个Trace.h头文件,并输入如下内容:
这段代码取自微软官方封装的WPP代码。
/*++Module Name:Trace.hAbstract:Header file for the debug tracing related function defintions and macros.Environment:Kernel mode--*///
// Define the tracing flags.
//
// Tracing GUID - 16803b14-05e0-4215-9336-06418469d132
//#define WPP_CONTROL_GUIDS \WPP_DEFINE_CONTROL_GUID( \KMDFDriver1TraceGuid, (16803b14,05e0,4215,9336,06418469d132), \\WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \WPP_DEFINE_BIT(TRACE_DRIVER) \WPP_DEFINE_BIT(TRACE_DEVICE) \WPP_DEFINE_BIT(TRACE_QUEUE) \) #define WPP_FLAG_LEVEL_LOGGER(flag, level) \WPP_LEVEL_LOGGER(flag)#define WPP_FLAG_LEVEL_ENABLED(flag, level) \(WPP_LEVEL_ENABLED(flag) && \WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \WPP_LEVEL_LOGGER(flags)#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)//
// WPP orders static parameters before dynamic parameters. To support the Trace function
// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to
// reorder the arguments to what the .tpl configuration file expects.
//
#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags)
#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags)//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//
最下面这段是伪指令,给编译器看的,目的就是生成Trace宏函数
//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//
然后在你的源文件中包含"Trace.h"头文件,包含好了我们在修改一下配置,让Visual Stuio知道Trace对应的描述文件是哪个,我们打开项目配置开始配置:
一、在Wpp Tracing中将Run Wpp Tracing设置为Yes,开启Trace日志功能
二、将Function And Macro Options中的Enable Infight Trace Recorder设置为yes,开启追踪功能,让日志输出到内核记录日志里去,这样就能用一些软件去读这个记录日志里读到我们的通过Trace打印的日志了。
三、在File Options中的Scan Configuration Data里输入我们刚刚创建的文件名,告诉编译器描述Trace文件是哪个。
包含了之后在你的文件中包含"driver.tmh"就可以了,这里的名称以你包含Trace.h的文件名称为例,在编译时编译器会自动编译Trace.h中的伪指令并生成对应的.tmh文件。
tmh文件里就包含了TraceEvents宏函数声明和实现
在使用TraceEvents函数之前需要先初始化,在你的DriverEvent里将它初始化:
WPP_INIT_TRACING(DriverObject, RegistryPath);
这里介绍一下TraceEvents的宏函数的使用方法:
TraceEvents(LEVEL, FLAGS, STR,...);
LEVEL表示信息模式级别,可以取以下值:
#define TRACE_LEVEL_NONE 0 // Tracing is not on
#define TRACE_LEVEL_CRITICAL 1 // Abnormal exit or termination
#define TRACE_LEVEL_FATAL 1 // Deprecated name for Abnormal exit or termination
#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging
#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure
#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases(e.g.,Entry-Exit)
#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps
#define TRACE_LEVEL_RESERVED6 6
#define TRACE_LEVEL_RESERVED7 7
#define TRACE_LEVEL_RESERVED8 8
#define TRACE_LEVEL_RESERVED9 9
FLAGS表示标志,即当前打印的发生在哪个标志上,当我们创建一个KMDF框架时一般分为三个文件:
Device.c 设备文件,在加载驱动时会调用,用于创建设备,比如Linux驱动加载以后会在Dev下创建一个设备文件
Driver.c 驱动文件,驱动代码
Queue.c 驱动退出相关代码
这三个分别对应不同事件时产生的,Device.c会在创建设备时被调用,而Driver.c则是驱动代码,用于驱动设备时会被调用,Queue.c则是在收尾时会被调用。
在打印时应针对不同的情况设置不同的FLAGS,所以FLAGS支持如下几个选项:
MYDRIVER_ALL_INFO:所有,通用设备信息
TRACE_DRIVER:驱动标志,表示当前处于驱动事件阶段
TRACE_DEVICE:设备标志,表示当前处于设备事件阶段
TRACE_QUEUE:收尾标志,表示当前设备驱动将进行uninstall
有时使用这些标志可能会出现未定义的情况,可以忽略,你build之后不会报错,这个原因可能是编译器生成tmh文件时缓存没有更新过来。
最后演示一下用法:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Hello Word!");
可变参数,可以像Printf一样使用
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Hello Word!%d",1);
当我们编译好并生成sys之后我们想要调试怎么办?
WDK提供了一个工具:traceview.exe,注意TraceEvents打印的只能用这款软件DbgView查看不到的。
你到WDK的安装目录下进入Tools-x64(x86)下能找到这款软件。
然后选中File-Create New Log Session,然后选择PDB调试的方式,我们生成的sys一般都附带了PDB文件,里面包含了调试信息,sys驱动文件路径等等。
选择你的PDB之后点击OK
然后点击Next
最后点击Finish,如果想保存Log可以选中Log Trace Event Data To File
最后我们设置事件等级,双击Level
因为我们里面使用的是TRACE_LEVEL_INFORMATION,所以选中Information
最后FLags全都选中,然后点击OK就可以了
到这一步日志系统就准备好了,那么就剩最后一步,就是加载驱动。
WDK自带了一个devcon.exe的工具,但是用起来不是那么方便,这里我使用的是另外一个加载的工具,Windows也提供了SC加载服务的API函数,大家可以利用这些函数实现自己的加载工具。
我使用的是:DriverMonitor,同时也有:KmdManager,这两款加载工具目前还是不错的。
以下是这两款软件的截图,同时附上下载地址:SysLoader驱动加载程序,用于调试驱动-WindowsServer文档类资源-CSDN下载:
DriverMonitor:
KmdManager:
这里我使用的是DriverMonitor,以管理员权限打开它,然后选择:File-Open Driver...
选择你的Driver
然后点击GO图标会开始调用驱动代码,DriverCreate函数是在加载驱动时调用的,当点击GO图标时调用的驱动代码是DriverEntry函数。
当我们执行的时候它报了一个错误:
翻译过来就是Windows无法验证数字签名,这个是在Win7以后的系统都需要数字签名,如何申请签名这个后面说,先教大家在调试时解决这个问题,大家可以在Win10的Setting界面进入高级选项,关闭数字签名,具体可以Web搜索一下Win10关闭数字签名
然后就可以了
同时在TraceView中可以看到对应的输出:
当我们想删除驱动时可以点击X图标就可以了
Windows Driver开发_TraceEvents调试以及加载驱动的方法相关推荐
- rd450linux系统,RD450 板载r110i raid 安装RHEL 6.5 x64 加载驱动的方法(UEFI引导模式)...
CentOS 6.5 x64通用.所有联想服务器 R110i的raid卡通用. 因为联想没有CentOS系统的驱动,可以用RedHat的驱动,找到对应的版本,我用过可以. 本方法按照RD450 OS安 ...
- Windows Phone开发之路(14) 加载位图
除了文本之外,位图是Silverlight程序中最常见的对象之一,通常我们将其定义为与图形显示设备的像素相对应的二维比特(bit)数组. Windows原生的位图文件的扩展名是bmp,但是近年它已不占 ...
- iOS开发UI中懒加载的使用方法
1.懒加载基本 懒加载--也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其getter方法.说的通俗一点,就是在开发中,当程序中需要利用的资源时.在程序启动的时候不加载 ...
- Windows 10搜索框一直搜索/加载的解决方法
重装了win10系统后,发现搜索框输入完内容就一直在加载,什么东西也搜索不到. 神奇的是切换到Administrator账户使用起来就没有问题.于是把自己账户权限改到最高,但问题并没有解决. 百度给了 ...
- Windows Driver开发_NT Driver框架:The driver is not in a state to accept this command
通常我们可以使用一些驱动加载工具来改变我们驱动的行为,如加载驱动时执行入口函数与卸载函数,这里是我用当我们点击Start时会调用DriverEvent函数,并且正常加载 但当我们点击Stop卸载时确报 ...
- iOS开发UI篇—懒加载
iOS开发UI篇-懒加载 1.懒加载基本 懒加载--也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了, ...
- 成功解决:将后缀.pyx格式文件(linux环境)编译成pyd文件(windows环境下)实现python编程加载或导入
成功解决:将后缀.pyx格式文件(linux环境)编译成pyd文件(windows环境下)实现python编程加载或导入 目录 解决问题 解决思路 解决方法 解决问题 .pyx格式文件,在window ...
- Chrome 调试动态加载的js
今天有个同事问到我用chrome调试动态加载js的问题,这个问题之前遇到过,只是时间有点长了,有些忘记.在这里做一下记录: 在要调试的源码的后面加上 //@ sourceURL= debug.js 注 ...
- 通过安装和配置AD域解决Windows Server 2016的IIS无法加载SMB文件卷文件的问题
通过安装和配置AD域解决Windows Server 2016的IIS无法加载SMB文件卷文件的问题 1. 问题描述 通过客户反馈我们发现Windows Server 2016的IIS无法加载SMB文 ...
最新文章
- Python Json存储与读取
- 几张旧照片,用傻瓜拍的,翻出来凑数 (续)
- android 调用java接口_android调用java的web service接口
- java super用法_Java基础面试题汇总
- Python AttributeError: 'module' object has no attribute 'posseg'
- 自己在win10中添加ADO控件步骤总结
- 数据科学 IPython 笔记本 7.15 高性能 Pandas
- 自适应滤波器原理第四版计算机实验,自适应滤波器原理(中文第4版)答案
- Python框架篇之Django(基本流程、命令行、配置文件)
- 怎么用bat关闭远程协助计算机,Windows批处理请求远程协助
- slqite3库查询数据处理方式_SQLite数据库使用 常用命令
- RazorSQL for Mac:查看和编辑二进制数据和图像
- R语言系列:分布一致性和离散一致性检验
- 清华大学c语言程序设计课件,c语言清华大学课件
- 飞机遭遇时空乱流离奇穿越到30年前
- 服务器怎么查看c盘大文件在哪里,怎么快速查找系统中的大文件?
- 笔记本搜不到WiFi是什么原因
- 用stata计算同比增长率的两种方法
- sap crm button_如何安装SAP软件?
- 六方面的学习,帮你走上业务架构师之路
热门文章
- int 最大值_十行代码说清楚:leetcode 队列的最大值
- js怎么给div加滑动条 vue给弹出层加滑动条(一分钟学会用js加滚动条)
- java future 返回值_Java--Callable与返回值future
- 基于hadoop构建对象存储系统_基于Hadoop企业私有云存储平台的构建
- python read函数参数_最新Pandas.read_excel()全参数详解(案例实操,如何利用python导入excel)...
- sql重复数据只保留一条_一条SQL完成跨数据库实例Join查询
- android beam 第三方 aar,NFC通讯之Beam方式
- linux中dir命令,详解Linux系统中ls和dir命令的组合使用
- python 检查域名是否可以访问_糖尿病人是否都要做喝糖水的检查?结果可以说明胰岛功能水平吗?...
- 计算机骗局案例,骗局揭秘 | 卖你一台假电脑,再送你一个假鲁大师