某某茶叶有限公司欢迎您!
金沙棋牌在线 > 操作系统 > Windows驱动开发入门指引

Windows驱动开发入门指引

时间:2019-11-28 19:16

   1.  前言

      摘要:

[序言]
很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从事驱动开发时间不长也不短,大概也就3~4年时间.大多数人都认为会驱动开发的都是牛人,高手之类的.其实高手,牛人不是这样定义的.我们在学习驱动开发之前,一定要明白一个道理:术业有专攻,不要盲目跟风.

Windows的驱动开发模型

因工作上项目的需要,笔者需要做驱动相关的开发,之前并没有接触过相关的知识,折腾一段时间下来,功能如需实现了,也积累了一些经验和看法,所以在此做番总结。

      许多开发者想学习使用测试驱动开发实践,Brendan在本篇文章中说明了怎样在写代码之前编写测试。

[贡献者]
1> defddr   看雪学院
2> StudyRush看雪学院

 

对于驱动开发的开发指引,微软官方文档网站已经提供了很详细的教程文档,并且在Github上提供了一系列典型的例程源码用于开发人员参考。开发人员在具备一定的驱动概念知识后,通过参考官方例程可以很容易实现拥有特定功能的驱动应用程序。

      引言

[本内容适用环境及工具]
1> Windows系统下
2> VS2003版本以上
3> Windows驱动开发包(DDK(老版本) WDK(新版本))
4> 有能力着可以安装VMWare

    在Windows的不同版本上开发的驱动程序“模型”(模型这个词语应该来源于单词“Mode”。在Windows NT上,驱动程序被称为Kernel Driver Mode驱动程序。笔者认为这个Mode是指一种驱动程序的结构和运作的规范),有过不同的名称。比如在Windows 9x上的驱动程序,都叫做VXD,而在Windows NT上的驱动程序被称为KDM驱动程序,Windows 98~2000这个时期出现的新模型叫做WDM。
    Windows的驱动模型概念,本来是就驱动程序的行为而言的。比如WDM驱动,必须要满足提供n种被要求的特性(如电源管理、即插即用)才被称为WDM驱动。如果不提供这些功能,那么统一称为NT式驱动。同样的,WDF驱动也有它的一系列规范。
    但是本书采用简单的区分方法。将一切在Windows 2000~Windows Vista下能正常运作且未调用WDF相关的内核API函数的驱动都称为传统型驱动(包括NT式和WDM)。如果调用了WDF相关的内核API则称为WDF驱动。
请注意:WDF驱动是可以调用传统型驱动所调用的内核API的,WDF可以视为传统型的升级版。
    模型的发展并不是和操作系统版本的升级齐步走的,而是有一个逐渐替代的过程。比如Windows 98已经支持部分的WDM驱动程序,但是又支持一部分的VXD驱动。而到了Windows 2000,则VXD这种驱动程序完全被淘汰了。KDM则是WDM的前身。WDM是在KDM的基础上增加了一些新的特性,制定了一些新的规范而造就的。绝大部分函数调用都是通用的。当然,Windows 9x系列的内核完全不同,所以VXD与之相比,就没有一个内核API函数是一样的。
    故而随着Windows 9x的失宠,VXD难逃彻底被淘汰的命运。Windows NT则发展成了后来的Windows版本,KDM也变成了WDM而存在下来。当然,微软不会闲着,现在又推出了新的WDF。读者又不得不担心:本书是用WDM写的还是用WDF写的呢?会不会刚刚学完又被淘汰呢?
    和VXD不同,从KDM到WDM再到WDF是一脉相承的,基本上KDM程序员在学习WDM时已经占尽了便宜。到WDF也不例外,WDF与其说是新的驱动开发模型,还不如说是在已有的内核API和数据结构的基础上,又封装出一套让使用者觉得更简单、更易用的以Wdf-开头的一组API。因此,读者大可不必担心WDF的发展会让前面学习传统型驱动的努力付之东流。一个典型的例子是:大约在1991年到1992年间发布首个版本的硬盘上层过滤diskperf的代码,18年过去了,今天依然可以编译并正常在最新版本的Vista上运行。
    本书对于大部分无法找到WDF实例的章节,都采用了传统型驱动进行说明。比如磁盘过滤、文件系统过滤和网络中间层驱动。此外为了从简单入手,对于入门级的两个例子(串口和键盘)也使用了传统型驱动。但是虚拟磁盘和虚拟网卡(第5章和第11章),使用了WDF版本的例子,请读者注意识别。

Windows驱动程序入门:

      作为软件开发者,几乎都可能会遇到过围绕测试驱动开发方面的宣传。许多个人和组织现使用的已是过时而不是新近流行的理念。有许多的测试框架、模拟框架、注入容器和许多其他工具供测试者使用。也有各种不同的方法去进行测试,因此我首先指出除了我在本文中描述的方法外还有其他可行的方法。
      在本篇文章中,我将使用一些工具,下面是下载地址:
      Visual Studio 2008:开发环境
      RhinoMocks:模拟框架
      NUnit:测试框架

[本内容适用群体]
1> 具有C/C++语言基础的人
2> 具有80x86汇编基础的人
3> 具备高中以上文化水平的逻辑思维

Github:

      首先创建测试

[具备Windows系统理论书籍]
1> Windows核心编程
2> Win32多线程程序设计
3> 深入解析Windows操作系统
4> Windows操作系统原理

 

      有种说法来自与人们经常听到的在他们写代码之前应先写测试时说的话,“这正好会创建一个编译错误”。这是对的,但记住我说过做事情有各种各样的方式。如果你不想这样的话里你不必提前创建测试,但我建议你这样做。我们为什么首先要创建测试至少出于两个原因:它有助于确保我们所做的工作的正确性,并且也提供出了测试的代码所期望的接口。
      确保测试的准确性
      我要告诉你的是,在有些地方,你要写你预期失败的测试方法而不是只让它通过。这有太多的原因会导致这样的情况,但这样的话在每天结束的时候,你写的测试并不能准确地验证你的代码。这样所有这些情况都会让测试错误的通过:互换了小于或者大于符号,忘记了断言语句,或者有时事情并不是按你所预期的进行。测试先行让你能确保你做的每件事情的正确性。
      创建期望的接口
      有时开发者要花费大量的时间去试图找出他们的代码所想要使用的接口。你想怎样在一批代码间进行交互和使用呢?最佳途径之一是找出它的一个用例并尝试去使用它。测试给出的是大的用例:他们说明了怎样去使用一个特定的类或者方法以及处理的结果是什么。因此我们如果假想测试使用了我们的类,在我们写类之前,我们就能给出想用来访问该类的接口。这意味着什么呢?这意味着我们现在知道了怎样去定义之间的交互接口,因为我们已经试图去使用过它。
      假如我们没有这样做的话,我们会基于一个假设去定义我们应该怎样去和我们打算创建的代码进行交互。要记住在代码修改之前写测试的价值。我认为这是有益的,但是这只是其中的一个观点,你可以轻松地以其他的方式进行。

FAQ1:为什么需要[具备Windows系统理论书籍]这4本书?
答:驱动是Windows系统的一个重要的组成部分,深入Windows系统核心的一个体系,就因为驱动跟系统内核联系得十分紧密,所以涉及了不少系统的基础理论以及原理.因此在学习驱动开发之前必须先明白Windows系统的基础开发理论,Windows系统的运作原理,Windows系统的架构体系.那么我提供的上面4本书是目前市面上我认为最经典最全面的书籍了.

   2.  驱动类型

      创建两个简单的测试

[具备Windows驱动开发书籍]
1> Windows驱动开发技术详解
2> Windows设备驱动程序WDF开发

 驱动分为如下几种类型:

      要开始了,我们想要去做的事情很容易,就是去验证我们想测试的东西的类型以及我们怎样去测试它们。在我们深入我们的第一个测试之前,我会尽可能给出我们的应用程序范例方面的一小点背景知识。我们打算写一个扑克牌游戏。从本文章的目的出发,我们将把我们的关注点放在游戏中的几个类上:Deck、Card和Player。
      我们应该始终以最简单的方式去做我们想做的事情。我们需要做的第一件事是找出我们的代码应该完成的任务。然后我们想写一个测试去断言我们的代码是以所期望的方式执行。
      为你的测试取名是极其重要的。假如你没有很好地对你的测试命名,在以后你将不知道它测试的是什么并且你可能会突然离题而去测试完全不同的东西。你要让描述能充分说明问题,但你也需要简洁。对于这第一个测试,我们将使用DeckCountShouldEqualCardCount这个名称。我们接下来的是一个称为DeckShouldHaveOneLessCardAfterDrawing的测试。有人读到这些名称时会认为我疯了,但我要提醒你的是,你要为每一个类都进行测试而它们都没有名称,当测试失败的时候你不知道是哪里发生了错误。这种具有描述性的名称会马上告诉你是哪里失败了,因为这些信息就包含在名称中。
      我们知道,我们需能绘制扑克牌并且在我们绘制好一张牌后其一副牌就应该减少一张,因此我们应该先创建一副牌的集合并跟踪其集合的数目。然后,我们绘制了一副牌的集合中的一张牌后要断言这个集合中的扑克牌的数目应该减一。以下是我们的第一个测试方法。
      清单1:简单的测试

FAQ2:为什么需要[具备Windows驱动开发书籍]这2本书?
答:假设你对Windows系统的基础理论扎实了,也看完了所说的[Windows系统理论书籍]这4本书,而且你还从事开发过Windows程序或者大程序的经验者.那么你进入Windows驱动开发的时候,需要一本经典的驱动入门开发书籍即可正确入门.现在我提供了[Windows驱动开发书籍]这2本书完完全全针对Windows驱动开发入门而编写的书籍.当然我首要推荐<Windows驱动开发详解>这本书.本书的内容在目前来说,针对驱动开发的讲解时非常到位了.包含了驱动开发理论 配置 驱动体系 等等......是一本不可多得的好书.那么第2本,其实有点滥竽充数,但是他里面有少少涉及到WDF这个最新的驱动开发理论的讲解,大家也就凑合着吧.

  • 设备函数驱动程序
  • 设备筛选器驱动程序
  • 软件驱动程序
  • 文件系统筛选器驱动程序
  • 文件系统驱动程序

[Test]
public void DeckCountShouldEqualCardCount()
{
    var cards = new List<Card> {new Card(), new Card(), new Card()};
    int initialCardCount = cards.Count;

[具备Windows调试基础理论书籍]
1> 软件调试
2> Windows用户态程序高效排错

驱动程序不是一定需要与硬件通讯,如果需要访问操作系统核心数据,往往应用程序没有足够的权限,这种情况则需要在内核模式下进行访问。就上面5种驱动类型,笔者参考着微软的驱动例子开发过 鼠标键盘设备过滤驱动网络过滤软件驱动程序,所以对驱动开发的理解仍在浅水区,如在阅读过程中发现有误的地方,还请不吝指出。

    var deck = new Deck(cards);

FAQ3:为什么需要[具备Windows调试基础理论书籍]这2本书?
答:在开发驱动的情况下,你少不了要调试驱动程序.那么如何调试驱动程序呢? Windows已为你考虑到这个问题了并开发了一套强有力的调试工具:Windbg .如何学习这个工具的调试呢?那么现在市面上只有这2本书针对Windbg讲解得还比较到位,至少针对调试命令的使用,已经用中文讲解了,大家可以通过2本书先大概了解Windbg的调试命令,然后再进一步进行GOOGLE搜索并深入学习.