上篇《Windows 驱动开发 - 基础2》已经介绍了windows大概的框架。那么使用WDF有那些的不同呢?
我们知道在WDF中,KMDF是必须的。而KMDF是架构在WDM之上的。
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 表现了这个概念。有些例程,例如 DriverEntry 和 AddDevice,还有与几种 IRP 对应的派遣函数将出现在每一个这样的容器中。需要对 IRP 排队的驱动程序一般都有一个StartIo 例程。执行 DMA 传输的驱动程序应有一个 AdapterControl 例程。大部分能生成硬件中断的设备,其驱动程序都有一个中断服务例程(ISR)和一个推迟过程调用(DPC)例程。驱动程序一般都有几个支持不同类型IRP 的派遣函数,其中三个派遣函数是必须的。所以,WDM 驱动程序开发者的一个任务就是为这个容器选择所需要的例程。
一个基本的WDF驱动:DriverEntry和EvtDeviceAdd
(C:/WinDDK/7600.16385.1/src/usb/osrusbfx2)
/*++ Step1: This step shows how to create a simplest functional driver. It only registers DriverEntry and EvtDeviceAdd callback. Framework provides default behaviour for everything else. This allows you to install and uninstall this driver. --*/ #include "ntddk.h" #include "wdf.h" #include "prototypes.h" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { WDF_DRIVER_CONFIG config; NTSTATUS status; KdPrint(("DriverEntry of Step1\n")); WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd); status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE ); if (!NT_SUCCESS(status)) { KdPrint(("WdfDriverCreate failed 0x%x\n", status)); } return status; } NTSTATUS EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status; WDFDEVICE device; UNREFERENCED_PARAMETER(Driver); status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device); if (!NT_SUCCESS(status)) { KdPrint(("WdfDeviceCreate failed 0x%x\n", status)); return status; } return status; }