Windows驱动开发之入门篇(一)

时间:2023-01-10 19:01:16

        本文主要介绍“如何入门Windows驱动开发”和“新手需要掌握哪些知识和动手技能”,大部分是本人探索Windows驱动开发近一月时间的经验之谈。大致包括如下几个方面:

1,开发工具、调试工具和调试手段;

2,Windows驱动开发框架;

3,驱动程序基本知识;

4,PCIE驱动程序;

5,学习资料

        以上内容在本文仅做简单介绍,后续随着本人经验的增加,将经常更新本文,并对有些内容单独开篇进行讲解。

        参考MSDN文档:点击打开链接

一、开发工具

1,虚拟机和操作系统

        本人使用的win10操作系统,并安装了“VMware Station11”,在虚拟机中暂时只安装了一个“win7 x64”操作系统,后续将安装一个win10虚拟机系统。一般情况下,我都是在虚拟机操作进行驱动的安装和调试,这样可以防止将本机的操作系统弄乱。

        后续将尝试“通过本机winDbg来调试虚拟机中的驱动”。这是一个比较高级的调试方法,点击打开链接

2,开发工具

        本人主要使用“WDK7600”(点击打开链接)和"VS2015+wdk10"(点击打开链接)。我把前者安装在“win7 X64”虚拟机中安装,把后者安装在本机和实验室电脑上。由于我使用的教材《Windows驱动开发详解》和学习博客都是用wdk7这个版本开发,为了环境一致,故选择了在虚拟机上试验这些教材上的示例代码。

        关于wdk7,参考博客:点击打开链接

        关于“VS2015+wdk10”,需要在win10系统下,先安装VS2015,再安装wdk10,此外还要安装VS2015的update。(winDbg集成到了wdk10下,路径:C:\Program Files (x86)\Windows Kits\10\Debuggers\x64)。

注意事项:

1)VS2015默认安装,是不安装c++和sdk的,需要选择自定义安装;

2)如果已经默认安装了,这个时候再安装wdk10,会给出警告;

3)此时,可以选择先用VS2015新建一个c++项目,然后会提示你安装c++部分的模块;

4)安装好后,就可以正常安装wdk10了,如果wdk10安装好后,还有编译问题,也需要先去VS下看看是否却c++相关模块,并按上述3安装完整。

另一个需要注意的是,编译报“Inf2Cat error -2: "Inf2Cat, signability test failed. "Double click to see the tool output”,

参考博客:点击打开链接

是因为inf文件的“DriverVer”的时间不对,VS2015默认的“Inf2cat”中的时间为UTF,需要在工程属性-》“inf2cat”选择中,将local时间打开。

3,调试工具

1)debugview

        在驱动程序中,调用KdPrint函数(类似C语言中printf),然后通过debugview查看打印信息。这是最常用的一种调试方法。

需要注意的是:首先要在“capture”菜单中勾选“kernel”相关的选项,表示抓取内核的信息。然后,需要使用“管理员身份”运行该软件。Debugview在win10下经常报错:

Windows驱动开发之入门篇(一)

需要到“C:\Windows\System32\drivers”中找到“dbgv.sys”,删除它,再使用“管理员身份”运行该软件。

2)


4,调试手段

1)驱动安装阶段,可以到“C:\Windows\System32\drivers”目录下看相应的“sys”文件是否到位。

2)cmd->regedit打开注册表,再在“编辑”菜单下“查找”对应的设备信息。

3)使用KdPrint函数打印log和DebugView软件抓取log(最常用的手段);

4)在驱动代码中写log文件(理论上可行,待探索);

5)存储dump信息。所谓dump信息,就是在系统奔溃之前,操作系统会将当前的调用堆栈记录成一个dump文件。(详细设置系统转存dump信息,可以参考《Windows驱动开发技术详解》最后一章,或博客:点击打开链接)。设置好dump文件后,遇到蓝屏,再将dump文件放到WinDbg中查看,这也是一个中常用的调试手段。

6)IRPTrace,这个软件可以跟踪IRP,但是win7及后续版本都不可用,可以尝试自己写程序跟踪。

7)PCITree,查看设备挂载;

8)WinObject,查看驱动中的各种对象信息。

9)WinDbg调试虚拟机,这是一个高级应用。配合VS2015可以查看“内存”、“调用堆栈”、“线程”和“反汇编”。

注:在驱动的开发过程,需要逐渐掌握各种工具和调试手段。


二、开发框架

        从我最近的浏览的资料来看,Windows驱动程序大致有三种类型:NT驱动、WDM驱动和WDF驱动。其中,NT驱动是非即插即用(Plug-in-and-Play,PNP)式的,它是一项系统服务,目前的设备类驱动大都不是这种类型,不是我的关注点,后面将不展开介绍。WDM驱动和WDF驱动都是即插即用的驱动,后者是前者的升级版。

1,WDM框架

        WDM是早前的Windows驱动开发框架,虽然现在微软推荐用WDF,但是,学习WDM一是能够更对地了解操作系统的内部机制(WDF是对WDM更高层次的封装),二是《Windows驱动开发技术详解》以及网上的很多博文都是用的WDM,从学习角度出发也需要掌握一定的WDM知识。

        WDM框架的基本知识,可以参考博文:点击打开链接。后续我也用单独的博文来讲解这方面的内容,主要包括:

1)驱动对象与设备对象(DriverObject vs Device Object);

2)物理设备对象(PDO)和功能设备对象(FDO);

3)驱动的层次结构:水平层次(eg:FDO之间)和垂直层次(FDO到PDO);

4)入口函数(DriverEntry);

5)设备扩展(DRIVER_EXTENSION);

6)重要的例程(routine):AddDevice

7)IRP机制(I/O Request Package):MajorFunction(MJ))和MinorFunction(MN);


2,WDF框架

        对于WDF框架,可以参考《Window7设备驱动开发》这本书。WDF框架可以分为KMDF(Kernel Model Driver Frame)和UMDF(User Model Driver Frame),其驱动模型如下:

1)WDF对象(属性、方法和事件);

2)即插即用和电源管理的集成;

3)集成的I/O排队和取消(queue);

4)I/O模型。在Windows中,IRP的功能不仅仅是向驱动程序提供传统的I/O请求(读、写、创建等)。它是操作系统和驱动程序、驱动程序和驱动程序之间一种基于数据包的通信机制。


3,一个典型的KMDF驱动程序

        通过VS2015新建一个项目,选择“KMDF”,它会产生如下文件:

Windows驱动开发之入门篇(一)

1)public.h中定义GUID和CTL_CODE,并提供给应用程序使用;

2)trace.h定义的调试宏和函数,暂不关注;

3)driver.h和driver.c定义了主要的框架代码。包括:入口函数(DriverEntry)、加载设备的例程(KMDFDriver1EvtDeviceAdd)和清理上下文区的函数。该文件都是框架性的代码,在驱动开发的过程中,可以选择一个框架,选定框架后,一般不在该文件中添加功能,而是放到“device.c”和“queue.c”。

4)device.h和device.c,主要处理设备相关的功能,与设备交互的实现放在该文件中。主要包括设备初始化和资源释放;

5)queue.h和queue.c,主要处理IRP,包括KMDFDriver1EvtIoDeviceControl;