Enterprise Just Builder

Solution for Enterprise Software Architecture

wdm

WDF 驱动程序开发

设备驱动程序是硬件设备连接到计算机系统的软件接口,任何设备都必须有相应的驱动程序才能在计算机系统上正常工作。设备驱动程序的优劣直接关系到整个系统的性能和稳定性,因此,设计和开发稳定高效的驱动程序具有重要意义。

WDF (Windows Driver Foundation) 是微软新一代驱动程序模型,它在 WDM (Windows Driver Model) 的基础上发展而来,支持面向对象、事件驱动的驱动程序开发,提供了比 WDM 更高层次的抽象,是高度灵活、可扩展、可诊断的驱动程序框架。WDF 框架接管了驱动和操作系统内核的大多数交互,驱动和操作系统的交互交给框架内封装的方法(函数)完成,从而对二者进行了隔离,这样驱动开发者只需专注处理硬件的行为即可。另外 WDF 还将大多数驱动中都需要处理的 PnP (即插即用)和电源管理封装进了框架,成为了公用的驱动程序功能。

WDF 可以开发内核模式驱动, 也可以开发用户模式驱动,二者采用同一套对象模型构建,即 WDF。对于内核模式对象和用户模式对象来说,WDF 是它们的父对象。换言之两者都是从 WDF 派生而来的。针对内核模式派生出来的对象称为 KMDF;针对于户模式派生出来的对象称为 UMDF。无论何种模式的框架,其内部封装的方法、执行的行为其实还是用 WDM 来完成的。

本文主要针对 KMDF 框架展开讨论。

KMDF 对象模型
KMDF 驱动程序模型支持面向对象、事件驱动。它定义了一系列的对象用于表示设备、驱动、中断等,每个对象有其相应的属性、方法和事件。驱动程序利用这些方法创建对象、设置属性和响应事件。该框架定义的主要对象有:

>>> 阅读全文

 

, , ,

Linux和Windows设备驱动架构比较

本文将考查最为广泛使用的 Windows 和 Linux 操作系统的设备驱动架构。我们首先将展示并比较在这些操作系统中实现设备驱动所需的组件,然后讨论实现驱动程序的过程,包括对内核缓冲区执行 I/O 操作。在文章的末尾我们还将了解这些操作系统所提供的开发环境和基础工具。1

1.引言
现代操作系统一般都包含多个模块,如内存管理器、进程调度器、硬件抽象层和安全管理器等等。想进一步了解这两种操作系统的内核,这里有一些参考资料:关于 Windows 内核的细节,可翻阅 Russinovich 著的《Windows Internal》一书;而 Linux 内核则可以参考 Rusling 的《The Linux Kernel》或者 Beck et al 等合著的《Linux Kernel Internals》。对和各类型硬件设备交互来说,内核可被视为一个黑盒。那么能否将和所有已知设备交互的功能内建到内核中呢?有可能,但没有实际意义,因为这会无谓地消耗太多系统资源。

内核模块化
对于各种新设备,内核无法在创建时就预知如何与之交互。现代操作系统的内核允许通过运行时添加设备驱动模块来扩展系统功能,该模块实现的功能使得内核可以与某种特定的新设备交互。这些模块通常都会实现一个例程供内核在模块被加载时调用,此外还有例程则在模块被移除时调用。模块还会实现各种不同的例程以便实现 I/O 功能,如将数据传送到设备或从设备接收数据;同时还有例程以便向设备发送 I/O 控制指令。以上所述对 Linux 和 Windows 两种驱动架构均适用。

本文的组织结构
本论文分成下面几节:

  • 对两种驱动架构的一般介绍 (第二节)
  • 详细论述两种驱动架构的各个组件 (第三节)
  • 驱动程序范例,包括如何对内核缓冲区执行 I/O 操作(第四节)
  • 相关驱动开发环境和基础工具(第五节)

相关著作
Windows 设备驱动架构相关文档可在 Windows 驱动开发包(DDK)中找到. 此外 Walter Oney 和Chris Cant 在 《Writing Windows WDM Device Drivers》一书中对 Windows 驱动架构进行了详细介绍。Linux 设备驱动架构可以参考 Rubini 的《Linux Device Drivers》,该书可免费获取。

>>> 阅读全文

 

, , , , ,

利用总线接口进行驱动间通讯

这里我们将讨论高级 WDF 驱动开发中最常见的话题之一: 驱动间的通信。当引入 Windows 驱动开发其他话题,貌似简单的驱动间调用很快就变成一系列无穷无尽的选项、功能以及晦涩难懂的 WDM 琐事。1

不过从这些讨论中我们看到了希望之光:总线接口还存在着并活跃在 Windows 中,它不但提供了简洁的、定义良好的方式用于驱动间通信,而且 KDMF 还提供了帮助例程用来快速生产或消费这些接口。

什么是总线接口?
正如其名称所示,总线接口是总线驱动为其子驱动提供的一种标准程序调用接口。总线驱动可以有多个总线接口,每个接口通过 GUID 标识。接口的使用者通过 PnP IRP 来查询接口并返回一个总线定义的数据结构,该数据结构可以包含任何总线驱动想要共享的数据或函数 (如图1-1)。

当总线驱动向其子驱动的提供总线接口时,我们预期只有该 PDO 设备栈中的驱动将使用此接口。这样在卸载驱动时就可以消除任何可能存在的竞态。因为设备栈是从顶向下被逐一销毁的,因此 PDO 总是最后一个被删除的设备。假如总线接口被其设备栈内的驱动所使用,我们就无需担心在 PDO 被删除之后,还有程序试图使用该接口。

总线接口不只是给总线的
显然在总线驱动之外总线接口也相当有用,驱动间通信很常见且不是所有的驱动间通信都只涉及到与自己的 PDO 交互。还好,操作系统中对总线驱动的支持相当普遍,因此过滤型驱动或 FDO 可以对适当的 PnP IRP 进行处理,并发布自己的总线接口。这意味着我们可以使用由另一不同的设备栈 (图 2) 产生的总线接口。

>>> 阅读全文

 

, ,