Windows Driver Mode 1

[返回] [下一章]

第一章:导言


以某种观点来看,Windows 2000或Windows 98都是由一个操作系统核心和多个驱动程序组成,这些驱动程序与系统中的硬件相对应。本书的内容全部都是关于驱动程序及其相关的技术。

[返回] [下一页]

操作系统概述


WDM模型为存在于Windows 98和Windows 2000操作系统中的设备驱动程序提供了一个参考框架。尽管对于最终用户来说这两个操作系统非常相似,但它们的内部工作却有很大不同。在这一节,我将对这两个操作系统做一个简要描述。

Windows 2000概述

图1-1是以我的视点所看到的Windows 2000操作系统,该图着重了驱动程序开发者所关心的特征。软件要么执行在用户模式中,要么执行在内核模式中。当用户模式程序需要读取设备数据时,它就调用Win32 API函数,如ReadFile。Win32子系统模块(如KERNEL32.DLL)通过调用平台相关的系统服务接口实现该API,而平台相关的系统服务将调用内核模式支持例程。在ReadFile调用中,调用首先到达系统DLL(NTDLL.DLL)中的一个入口点,NtReadFile函数。然后这个用户模式的NtReadFile函数接着调用系统服务接口,最后由系统服务接口调用内核模式中的服务例程,该例程同样名为NtReadFile。

 

1-1. Windows2000系统结构

我们经常说NtReadFile是I/O管理器的一部分。“I/O管理器(I/O Manager)”这个术语多少有些误导,系统中并不存在名为“I/O管理器”的单独执行模块。但当我们讨论围绕在驱动程序周围的操作系统服务“云”时,我们需要使用一个名字来代表,而“I/O管理器”就是我们通常使用的名字。

系统中还有许多与NtReadFile相似的服务例程,它们同样运行在内核模式中,为应用程序请求提供服务,并以某种方式与设备交互。它们首先检查传递给它们的参数以保护系统安全或防止用户模式程序非法存取数据,然后创建一个称为“I/O请求包(IRP)”的数据结构,并把这个数据结构送到某个驱动程序的入口点。在刚才的ReadFile调用中,NtReadFile将创建一个主功能代码为IRP_MJ_READ(DDK头文件中的一个常量)的IRP。实际的处理细节可能会有不同,但对于NtReadFile例程,可能的结果是,用户模式调用者得到一个返回值,表明该IRP代表的操作还没有完成。用户模式程序也许会继续其它工作然后等待操作完成,或者立即进入等待状态。不论哪种方式,设备驱动程序对该IRP的处理都与应用程序无关。

执行IRP的设备驱动程序最后可能会访问硬件。对于PIO方式的设备,一个IRP_MJ_READ操作将导致直接读取设备的端口(或者是设备实现的内存寄存器)。尽管运行在内核模式中的驱动程序可以直接与其硬件会话,但它们通常都使用硬件抽象层(HAL)访问硬件。读操作最后会调用READ_PORT_UCHAR从某个I/O口读取单字节数据。HAL例程执行的操作是平台相关的。在Intelx86计算机上,HAL使用IN指令访问设备端口,在Alpha计算机上,HAL使用内存提取指令访问设备实现的内存寄存器。

驱动程序完成一个I/O操作后,通过调用一个特殊的内核模式服务例程来完成该IRP。完成操作是处理IRP的最后动作,它使等待的应用程序恢复运行。

Windows 98概述

图1-2显示了Windows 98的基本结构。其操作系统内核称为虚拟机管理器(VMM),因为它的主要工作就是创建“虚拟”机器,这些虚拟机器共享同一个物理机器。Windows3.0引入虚拟设备驱动程序(VxD)的原始目的就是为了虚化设备,以帮助VMM实现每个虚拟机器都拥有全部硬件的假象。VMM架构也被引入Windows 98,并能处理新硬件和32位应用程序。

 

1-2. Windows 98系统结构

Windows 98不能象Windows 2000那样整洁地处理I/O操作。在处理磁盘操作、通讯口操作、键盘操作,等等方面与Windows 2000有很大不同。Windows 98以两种完全不同的方式为32位应用程序和16位应用程序提供服务。见图1-3。

 

1-3. Windows 98中的I/O请求

图1-3的左侧显示了32位应用程序的I/O请求处理过程。应用程序调用的Win32API(例如ReadFile)是系统DLL(如KERNEL32.DLL)中的服务例程,但应用程序仅能用ReadFile读磁盘文件、通讯口,和有WDM驱动程序的设备。对于其它种设备,应用程序必须使用基于DeviceIoControl的特殊方式。并且Windows 98的系统DLL含有与Windows 2000不同的代码。ReadFile的用户模式部分(如参数检验,Windows 2000在内核中实现)使用某个专用机制到达内核模式驱动程序。磁盘文件操作使用一种机制,串行口操作使用另一种机制,而WDM设备也有自己专用的机制进入内核。所有这些机制都利用软件中断30h来实现用户模式到内核模式的转换,但它们之间又完全不同。

图1-3的中间显示了16位Windows应用程序的I/O请求处理过程,右侧是MS-DOS应用程序的I/O请求处理过程。在这两种形式中,用户模式应用程序直接或间接地调用了用户模式的驱动程序,原理上,这些用户模式驱动程序可以直接操作机器硬件而不用其它系统部件支持。例如,Win16程序通过调用名为COMM.DRV的16位DLL间接地执行串行口I/O。(到Windows 95为止,COMM.DRV仍是一个单独的驱动程序,它挂在IRQ3和IRQ4上,直接向串行口芯片发出IN和OUT指令) 虚拟通信(指虚拟机器之间的沟通)设备(VCD)驱动程序通过截获I/O端口操作来保证两个虚拟机不同时访问相同的端口。如果以一种神秘的方式思考这个过程,你可以这样认为,用户模式驱动程序使用了一个基于I/O截获操作的“API”,象VCD这样的“虚拟化”驱动程序就是通过冒充硬件操作来实现假API服务的。

Windows 2000的所有内核模式I/O操作都使用一个公用的数据结构(IRP)。而Windows 98没有达到这样高度统一,其串行口驱动程序要遵从由VCOMM.VXD规定的port驱动程序函数调用规范,而磁盘驱动程序则遵从IOS.VXD实现的包驱动层次架构。其它设备类驱动程序也有其它的实现方式。

如果要把WDM引入Windows 98,就必须使Windows 98内部架构与Windows 2000非常类似。Windows 98包含了NTKERN.VXD(VMM32.VXD)系统模块,该模块含有大量Windows NT内核支持函数的Windows实现。NTKERN.VXD使用与Windows 2000相同的方式创建IRP并发送IRP到WDM驱动程序。实际上,WDM驱动程序几乎区别不出这两个环境的不同。

[返回] [上一页] [下一页]

Windows 2000驱动程序


Windows 2000系统可以使用多种驱动程序,图1-4显示了其中几种。

 

1-4. Windows2000中的设备驱动程序种类

  • 虚拟设备驱动程序(VDD)是一个用户模式部件,它可以使DOS应用程序访问x86平台上的硬件。VDD通过屏蔽I/O权限掩码来捕获端口存取操作,它基本上是模拟硬件操作,这对于那些直接对裸机硬件编程的应用程序特别有用。尽管这种驱动程序在Windows 98和Windows 2000中共享一个名称并且有相同的功能,但实际上它们完全不同。我们用VDD缩写代表这种驱动程序,用VxD缩写代表Windows 98中的虚拟设备驱动程序以示区别。
  • 内核模式驱动程序的分类包含许多子类。PnP驱动程序就是一种遵循Windows 2000即插即用协议的内核模式驱动程序。准确地说,本书涉及的所有内容都是面向PnP驱动程序的。
  • WDM驱动程序是一种PnP驱动程序,它同时还遵循电源管理协议,并能在Windows 98和Windows 2000间实现源代码级兼容。WDM驱动程序还细分为类驱动程序(class driver)和迷你驱动程序(minidriver),类驱动程序管理属于已定义类的设备,迷你驱动程序向类驱动程序提供厂商专有的支持。
  • 显示驱动程序是用于显示和打印设备的内核模式驱动程序。
  • 文件系统驱动程序在本地硬盘或网络上实现标准PC文件系统模型(包括多层次目录结构和命名文件概念)。
  • 遗留设备驱动程序也是一种内核模式驱动程序,它直接控制一个硬件设备而不用其它驱动程序帮助。这种驱动程序主要包括Windows NT早期版本的驱动程序,它们可以不做修改地运行在Windows 2000中。

内核模式驱动程序的属性

内核模式驱动程序有许多共有的属性,下面我将分别讨论这些属性。(注意,在这本书中,缩写“DDK”仅指Windows 2000 DDK,如果要讨论其它DDK,我将给出具体的名字)

·        可移植性

内核模式驱动程序的源代码应该可以移植于所有Window NT平台。WDM驱动程序在其定义中就规定了其源代码可以在Windows 98和Windows 2000之间相互移植。为了实现这种可移植性,驱动程序应该全部用C写,并且只使用ANSI C标准规定的语言元素。应避免使用编译器厂商专有的语言特征,并避免使用没有被操作系统内核输出的运行时间库函数(参见第三章)。如果不能避免驱动程序中的平台依赖,至少应该用条件编译指令隔离这些代码。如果严格遵循这些设计方针,那么仅需要重新编译连接源代码,生成的驱动程序就可以运行在任何新的Windows NT平台上。

在大多数情况下,WDM驱动程序的二进制映像可以兼容Windows 98和Windows 2000(32位版本)。如果仅使用WDM.H中声明的内核模式支持函数,那么可以很容易地实现驱动程序的源代码级兼容。但操作系统之间的差异会在某些地方影响驱动程序的移植性,我将在本书的多个地方讨论这个问题。

·        可配置性

内核模式驱动程序应避免对设备特征或某些系统设置作绝对假设,这些系统设置会随着平台的改变而改变。例如,在x86平台上,标准串行口使用一个专用的IRQ和8个I/O端口,这些数值持续20年从未改变。把这些值直接写到驱动程序中将使驱动程序失去可配置性。在第八章,我将讨论两个用户可控制的电源管理特征——空闲检测和系统唤醒;一个总使用特定空闲超时常量的驱动程序或者只利用针对自己设备唤醒特征的驱动程序将不能实现用户可控制。这样的驱动程序将是不可配置的。

为了实现可配置性,首先应该在代码中避免直接引用硬件,即使是在平台相关的条件编译块中也是这样。应该使用HAL工具或调用低级总线驱动程序,或者实现一个标准的或定制的控制接口,并通过控制面板程序与用户交互。另外,还应该支持Windows管理仪器(WMI)控件,这种控件允许用户和管理员在分布式企业环境中配置硬件特征(见第十章)。最后,应该使用注册表作为配置信息的数据库,这可以使配置信息在系统重新启动后仍然存在。

·        可抢先性和可中断性

Windows 2000和Windows 98都是多任务操作系统,可以为任意多个线程分配CPU时间。在大部分时间中,驱动程序例程执行在可以被其它线程(在同一个CPU上)抢先的环境中。线程抢先取决于线程的优先级,系统使用系统时钟为线程分配CPU时间片。

Windows 2000还使用了一个中断优先级的概念,即IRQL。我将在第四章中详细讨论IRQL,在这里我先简单介绍一下。你可以认为CPU中有一个IRQL寄存器,它记录着CPU当前的执行级别。有三个IRQL值对设备驱动程序有重要意义:PASSIVE_LEVEL(值为0)、DISPATCH_LEVEL(值为2),以及所谓的设备中断请求级DIRQL(大于2的值,设备的中断服务例程在该级上执行)。在大部分时间中,CPU执行在PASSIVE_LEVEL级上,所有的用户模式代码也运行在PASSIVE_LEVEL级上,并且驱动程序的许多活动也都发生在PASSIVE_LEVEL级上。当CPU运行在PASSIVE_LEVEL级时,当前运行的线程可以被任何优先级大于它的线程抢先。然而,一旦CPU的IRQL大于PASSIVE_LEVEL级,线程抢先将不再发生,此时CPU执行在使CPU越过PASSIVE_LEVEL级的任意线程上下文中。

你可以把高于PASSIVE_LEVEL级的IRQL看成是针对中断的优先级。这是一个与支配线程抢先机制不同的优先级方案,正如我前面说的,在PASSIVE_LEVEL级上没有线程抢先发生。但是,运行在任何IRQL级上的活动都可以被更高IRQL级上的活动中断。所以驱动程序必须假定在任何时刻都可能失去控制权,而此时系统可能需要执行更基本的任务。

·        多处理器安全

Windows 2000可以运行在多处理器计算机上。Windows2000使用对称多处理器模型,即所有的处理器都是相同的,系统任务和用户模式程序可以执行在任何一个处理器上,并且所有处理器都平等地访问内存。多处理器的存在给设备驱动程序带来了一个困难的同步问题,因为执行在多个CPU上的代码可能同时访问共享数据或共享硬件资源。Windows 2000提供了一个同步对象,自旋锁(spin lock),驱动程序可以使用它来解决多处理器的同步问题。(见第四章)

·        基于对象

Windows 2000内核是基于对象的,即驱动程序和内核例程使用的许多数据结构都有公共的特征,这些特征集中由对象管理器管理。这些特征包括名称、参考计数、安全属性,等等。在内部,内核中包含了许多执行公共对象管理的方法例程,例如打开和关闭对象或析取对象名。

驱动程序使用内核部件输出的服务例程来维护对象或对象中的域。某些内核对象,例如内核中断对象,是不透明的,DDK头文件中没有其数据成员的声明。其它内核对象,如设备对象或驱动程序对象则是部分不透明的,DDK头文件中声明了其结构的全部成员,但DDK文档中仅描述了可访问的成员并警告驱动程序开发者不要直接访问或修改其它成员。对于驱动程序必须间接访问的不透明域,可以用支持例程访问。部分不透明的对象类似于C++的类,有任何人都能访问的公共成员,还有必须通过方法函数才能访问的私有成员和保护成员。

·        包驱动

I/O管理器和设备驱动程序使用I/O请求包来管理I/O操作的具体细节。首先,某个内核模式部件创建一个IRP,该IRP可以是让设备执行一个操作、向驱动程序发送一个命令,或者向驱动程序询问某些信息的请求。然后I/O管理器把这个IRP发送到驱动程序输出的例程上。一般,每个驱动程序例程仅执行IRP指定的一部分工作然后返回I/O管理器。最后,某个驱动程序例程完成该IRP,之后I/O管理器删除该IRP并向原始请求者报告结束状态。

·        异步

Windows 2000允许应用程序和驱动程序在起动一个I/O操作后继续执行,而此时I/O操作仍在进行。所以,需要长时间运行的I/O操作应该以异步方式执行。即当驱动程序接收到一个IRP后,它首先初始化用于管理该I/O操作的任何状态信息,然后安排IRP的执行,而该IRP将在以后的某个时刻完成,最后返回调用者。由调用者决定是否等待该IRP的完成。

作为一个多任务操作系统,Windows 2000根据线程的适合性和优先级来调度它们在有效处理器上的执行。通常,驱动程序在某些不可预测线程的上下文中应该使用异步方式处理I/O请求。我们使用术语任意线程上下文(arbitrary thread context)来描述驱动程序并不知道(或并不关心)处理器当前执行在哪一个线程上的上下文。驱动程序应避免阻塞任意线程,这使得驱动程序有了这样的架构:通过执行离散的操作并返回来响应硬件事件。

WDM驱动程序模型

在WDM驱动程序模型中,每个硬件设备至少有两个驱动程序。其中一个驱动程序我们称为功能(function)驱动程序,通常它就是你认为的那个硬件设备驱动程序。它了解使硬件工作的所有细节,负责初始化I/O操作,有责任处理I/O操作完成时所带来的中断事件,有责任为用户提供一种设备适合的控制方式。

另一个驱动程序我们称为总线(bus)驱动程序。它负责管理硬件与计算机的连接。例如,PCI总线驱动程序检测插入到PCI槽上的设备并确定设备的资源使用情况,它还能控制设备所在PCI槽的电流开关。

有些设备有两个以上的驱动程序。我们使用术语过滤器驱动程序(filter driver)来描述它们。某些过滤器驱动程序仅仅是在功能驱动程序执行I/O操作时进行监视。多数情况是:硬件或软件厂商利用过滤器驱动程序修改现有功能驱动程序的行为。上层过滤器驱动程序在功能驱动程序之前看到IRP,它们有机会为用户提供额外的特征,而功能驱动程序根本不知道。有时,一个上层驱动程序可以修正功能驱动程序或硬件存在的毛病或缺陷。低层过滤器驱动程序在功能驱动程序要向总线驱动程序发送IRP时看到IRP。在某些情况下,例如当USB设备插入USB总线时,低层过滤器驱动程序可以修改功能驱动程序要执行的总线操作流。

WDM功能驱动程序通常由两个分离的执行文件组成。一个文件是类驱动程序,它了解如何处理操作系统使用的WDM协议(有些协议相当复杂),以及如何管理整个设备类的基本特征。USB照相机类驱动程序就是一个例子。另一个文件称为迷你驱动程序(minidriver),它包含类驱动程序用于管理设备实例的厂商专有特征例程。类驱动程序和迷你驱动程序合在一起才成为一个完整的功能驱动程序。

可以把一个完整的驱动程序看作是一个容器,它包含许多例程,当操作系统遇到一个IRP时,它就调用这个容器中的例程来执行该IRP的各种操作。图5-1表现了这个概念。有些例程,例如DriverEntryAddDevice,还有与几种IRP对应的派遣函数将出现在每一个这样的容器中。需要对IRP排队的驱动程序一般都有一个StartIo例程。执行DMA传输的驱动程序应有一个AdapterControl例程。大部分能生成硬件中断的设备,其驱动程序都有一个中断服务例程(ISR)和一个推迟过程调用(DPC)例程。驱动程序一般都有几个支持不同类型IRP的派遣函数,其中三个派遣函数是必须的。所以,WDM驱动程序开发者的一个任务就是为这个容器选择所需要的例程。

 

1-5. WDM驱动程序容器中的内容

[返回] [上一页] [下一页]

例子代码


本书的随书光盘中包含许多驱动程序例子和测试程序。编写例子程序的目的是为了配合文中讨论的问题或技术。但是这些例子仅仅是一些“玩具”而已,你不能仅改变几行代码后就发行它们。第七章和第十一章有一些可以驱动真正硬件的驱动程序例子,这些硬件就是PCI芯片厂商和USB芯片厂商提供的开发板,除此之外,所有驱动程序都是针对假想的硬件。

几乎每个驱动程序例子都带有一个简单的用户模式测试程序,你可以用它来检查例子驱动程序的操作。这些测试程序十分小,仅包含几行涉及被测试驱动程序特殊功能的代码。

随书光盘

光盘含有每个例子的完整源代码和执行文件。此外还有几个你可能用得着的工具程序。可以在WDMBOOK.HTM文件中看到例子程序的索引和工具程序的使用说明。

光盘中的安装程序可以把全部例子安装到硬盘上,当然也可以直接在光盘上使用这些例子。安装程序不会向你的系统目录安装任何内核模式部件。安装程序将询问你是否可以向AUTOEXEC.BAT文件中加入某些环境变量。Build程序可能需要这些环境变量。安装程序还向注册表中加入了必要的表项以定义一个SAMPLE设备类,所有例子驱动程序都属于这个SAMPLE设备类。

如果你的计算机上既有Windows 2000又有Windows 98,我建议你在其中一个操作系统上做一次完全安装,在另一个操作系统上做一个简便安装。(注意,Windows 2000不再使用AUTOEXEC.BAT文件初始化环境变量)

每个例子都有一个阐述如何创建和测试该例子的HTML文件说明,我建议你在安装一个例子驱动程序前先阅读这个说明,因为某些例子有特别的安装要求。一旦安装了某个例子驱动程序,你将在设备管理器中发现一个额外的属性页(如图1-6)。

1-6. 某个例子驱动程序的定制属性页

关于创建例子驱动程序

有一个原因可以解释为什么我的例子程序看起来都像从一个模子里印出来的:实际上,它就是用特殊的模子印出来的,由于要写许多例子驱动程序,所以我决定写一个应用程序向导。Microsoft Visual C++6.0的向导功能完全可以用于创建WDM驱动程序工程,我决定使用它。这个向导就是WDMWIZ.AWX,你可以在随书光盘中找到它。我在附录C中给出了它的用法。你可以用它构造驱动程序框架。但这个向导不是一个产品级软件,其用途仅是帮助你学习驱动程序编程。另外,由于这个向导功能有限,有时你需要手动更改驱动程序工程的某些设置。更详细的信息请参考WDMBOOK.HTM文件。

安装了Windows2000 DDK后,开始菜单上将出现checked build environment和free buildenvironment两个菜单项。每个环境都有与驱动程序创建方法相适应的环境变量。BUILD.EXE工具将根据不同的环境和工程描述文件SOURCES创建不同的驱动程序。我为每个例子驱动程序工程都提供了一个SOURCES文件。

我个人更喜欢用Microsoft Visual Studio环境管理驱动程序工程。过去我曾提倡使用BUILD.EXE工具,这是因为我担心Microsoft有一天会改变某些重要的编译连接选项,那样的话,任何基于IDE的方法都将被破坏。事实上,这种事情已经在Windows 2000的beta版中发生了。(有人决定修改沿用了十年的库文件结构,为此我就必须修改某些工程设置) 我认为使用IDE带来的高生产效率要比冒险在将来做某些修改更值得。

GENERIC.SYS

WDM驱动程序中包含大量处理即插即用和电源管理的代码。这些代码很长,另人厌烦,并且容易出错。所以我在所有依赖这些代码的驱动程序中都调用了GENERIC.SYS(内核模式DLL)来代替这些代码。WDMWIZ.AWX可以创建使用GENERIC.SYS的工程。附录B详细列出了GENERIC.SYS的输出函数。

[返回] [上一页] [下一页]

本书的结构


在教授了几年驱动程序编程讲座之后,我渐渐发现人们通常以两种不同的方法学习新事物。一些人喜欢先学会理论然后再学习实际操作。而另一些人喜欢先学习实际操作然后再学习理论。我把前者称为演绎方式,把后者称为归纳方式。我本人更喜欢归纳方式,所以我把这本书也组织成与归纳学习法相适合的结构。

我的目标是阐述如何写设备驱动程序。具体地说,我想为你提供一个写实际驱动程序所必须的最小的背景知识,然后再过渡到更专门的主题上。这个“最小背景知识”包含的内容很广泛,它占了本书的前六章。但是一旦你跨过了第七章,其后的章节虽然重要但对于写一个能工作的驱动程序来说并不是必须的。

  • 第二章,“WDM驱动程序的基本结构”解释了Windows 2000用于管理I/O设备的基本数据结构,以及驱动程序与这些数据结构相联系的基本方式。我将讨论驱动程序对象和设备对象。还将讨论两个基本例程:DriverEntry和AddDevice,每个WDM驱动程序“容器”都包含这两个例程。
  • 第三章,“基本编程技术”描述了一些最重要的服务函数,你可以调用这些函数来完成普通的编程工作。我还将讨论错误处理、内存管理,和其它一些编程技术。
  • 第四章,“同步”讨论驱动程序怎样在多任务和多处理器的环境中同步访问共享数据,你将详细地学习IRQL,学习用操作系统提供的各种同步原语解决同步问题。
  • 第五章,“I/O请求包”是本书的真正主题。我将解释I/O请求包从哪来,讨论IRP处理的“标准模型”。另外,我还将讨论一个更复杂的题目:IRP取消,它涉及到同步问题。
  • 第六章,“即插即用”仅涉及到一种类型的I/O请求包,即IRP_MJ_PNP。PnP管理器通过发送这种IRP来报告设备的配置,并在设备存在期间向驱动程序通知重要事件。多数设计良好的PnP驱动程序不能使用“标准模型”来处理IRP。所以,我描述了一个名为DEVQUEUE的对象,你可以在PnP事件发生时使用它来正确地入队(queue)和出队(dequeue)IRP。
  • 第七章,“读写数据”我们将在这一章里讨论执行I/O操作的驱动程序代码。我将讲述怎样从PnP管理器那里获得配置信息,怎样用这些信息初始化驱动程序,以使它能处理数据读写IRP。我还给出了两个简单的驱动程序例子:一个用于PIO设备,一个用于总线主控的DMA设备。
  • 第八章,“电源管理”描述了驱动程序如何参与电源管理。电源管理颇为复杂。不幸的是,你必须参与系统的电源管理协议,否则整个系统将不能正常工作。
  • 第九章,“专门问题”包含了对过滤器驱动程序、错误登记、I/O控制操作,和系统线程的讨论。
  • 第十章,“Windows管理仪器”涉及一个企业范围的计算机管理方案,你的驱动程序能够并且也应该参与这个方案。我将解释如何为监视程序提供统计数据和性能数据,怎样响应标准的WMI控制,怎样向控制程序报告重要事件的发生。
  • 第十一章,“USB总线”描述怎样写USB设备驱动程序。
  • 第十二章,“安装设备驱动程序”告诉你怎样把驱动程序安装到用户系统中,你将学习INF文件的基本写法,还可以学到关于系统注册表的一些有趣并且有用的东西。
  • 附录A,“Windows 98的不兼容处理”介绍一个基于VxD的方案,该方案允许你在Windows 98和Windows 2000平台上使用相同的驱动程序映像。由于Windows 2000出现在Windows 98之后,它输出了Windows 98没有输出或没有实现的服务例程,我将介绍一个短小的VxD程序,它可以解决这个问题。
  • 附录B,“使用GENERIC.SYS”描述了GENERIC.SYS的公共接口。大部分驱动程序例子使用了这个库。
  • 附录C,“使用WDMWIZ.AWX”描述了如何使用这个应用程序向导来创建一个驱动程序。我再提一下,WDMWIZ.AWX并不是一个商品化的工具包。

关于书中的错误

我尽可能使本书不出现错误。但是想一想,当写一本含有复杂技术和许多新概念的书时,你不可能保证百分之百的正确。另外,几个月后当Windows 2000从beta版变为正式版时,WDM不可避免地会有些改变。为此,我将在http://www.oneysoft.com/上发布一个勘误表。

[返回] [上一页] [下一页]

其它资源


本书并不是关于驱动程序编程的唯一资源。它仅着重描述了我认为重要的特征;但你有可能需要一些我没有涉及到的信息,或者你有与我不同的学习方法。我没有讲述超出驱动程序编制需求之外的操作系统知识。如果你是一个演绎式学者,或者你仅仅想知道一些理论背景,可以参考下面列出的资源。

驱动程序开发书籍

  • Art Baker,《The Windows NT Device Driver Book: A Guide for Programmers》,(Prentice Hall, 1997)。
  • Chris Cant,《Writing Windows WDM Device Drivers》,(R&D Press, 1999)。
  • Edward N. Dekker和Joseph M. Newcomer,《Developing Windows NT Device Drivers: A Programmer's Handbook》,(Addison-Wesley, 1999)。
  • Rajeev Nagar,《Windows NT File System Internals: A Developer's Guide》,(O'Reilly & Associates, 1997)。
  • Peter G. Viscarola和W. Anthony Mason,《Windows NT Device Driver Development》,(Macmillan, 1998)。

其它参考书籍

  • David A. Solomon,《Inside Windows NT, Second Edition》,(Microsoft Press, 1998)。

杂志

  • Microsoft Systems Journal偶尔会有一些关于驱动程序开发的文章。

新闻组

  • comp.os.ms-windows.programmer.nt.kernel-mode新闻组提供了一个讨论内核模式编程问题的论坛。

讲座

我办了一个WDM编程讲座,关于讲座的信息和时间表请访问http://www.oneysoft.com/。这个技术专题的讲座也有其他人在办,我们以此为生。我相信你能谅解我没有为你明确指出我的竞争者的地址链接。

[返回] [上一页]

注意事项


出于解释说明的目的,书中出现的代码没有做任何错误检测。我遵循这样的原则:尽可能一步一步地解释复杂的题目,而不是把你淹没在太多的代码中。

随书光盘中的例子驱动程序全部做了错误检测并且有产品级驱动程序所需要的一切内容。当你要向自己的代码中加入某些东西时,应该先查阅光盘。

原文地址:https://www.cnblogs.com/gooer/p/1818150.html