WDF设备驱动框架

2009-05-20 上午 06:49

1. 引言


设备驱动程序是硬件设备连接到计算机系统的软件接口,任何设备都必须有相应的驱动程序才能在计算机系统上正常工作。设备驱动程序的优劣直接关系到整个系统的性能和稳定性,因此,设计和开发稳定高效的驱动程序具有重要意义。
WDF(Windows Driver Foundation)是微软提出的下一代全新的驱动程序模型[1],它是在WDM(windows Driver Model)的基础上发展而来的,支持面向对象、事件驱动的驱动程序开发,提供了比WDM更高层次抽象的高度灵活、可扩展、可诊断的驱动程序框架。WDF框架管理了大多数与操作系统相关的交互,实现了公共的驱动程序功能(如电源管理、PnP支持),隔离了设备驱动程序与操作系统内核,降低了驱动程序对内核的影响。
WDF提供了两个框架:KMDF(内核模式驱动程序框架)和UMDF(用户模式驱动程序框架)。本文只介绍KMDF的设计与实现。

2. WDF对象模型
KMDF框架支持面向对象、事件驱动的驱动程序模型。它定义了一系列的对象用来表示设备、驱动、中断等,每个对象有对应的属性、方法和事件。驱动程序利用这些方法创建对象、设置属性和响应事件。
框架定义的主要对象有:
WDFDRIVER对象,对应于WDM中的DRIVER_OBJECT。描述驱动在内存中的实例,包括加载的位置、有关的属性和所管理的设备。
WDFDEVICE对象,对应于WDM中的DEVICE_OBJECT。描述由驱动程序管理的单个设备实例,设备可以是命名的也可以是未命名的。用户模式程序可以通过设备接口或设备名称访问设备。WDFDEVICE对象具有丰富的属性,如pnp和电源管理相关的事件处理回调函数(callbacks)。
WDFREQUEST对象,对应于WDM中的IRP,表示一个I/O请求。
WDFQUEUE对象:每个WDFQUEUE对象和一个WDFDEVICE对象关联,描述一个特殊的I/O请求队列。它具有一系列的事件处理回调函数,当I/O请求进入队列时,框架将自动调用驱动程序中对应的callback。
WDFINTERRUPT对象:表示设备中断。驱动程序可以通过WDFINTERRUPT对象的中断使能和禁止事件处理callbacks使能或禁止设备中断;通过ISR和DPCforISR例程处理设备中断。
WDF的对象模型是层次化的模型。WDFDRIVER对象是根对象,其他对象都是它的子对象。对于大多数对象,驱动程序在创建他们的时候可以指定父对象,如果没有指定,则框架默认其父对象为WDFDRIVER对象。
WDF大大简化了WDM中的pnp和电源管理的开发。WDF框架为设备停止、设备删除、电源状态切换等pnp和电源管理事件提供了适合的缺省行为,驱动程序本身不再纠缠于复杂的pnp和电源管理事件处理。此外,WDF还集成了请求队列的支持,一个设备可以有多个请求队列,每个请求队列可以有一种模式。最简单的是 WdfIoQueueDispatchSerial模式,在这种模式下,请求队列将请求串行化后再处理;而WdfIoQueueDispatchParallel模式则自动在每个请求到来时调用相应的回调函数;最后WdfIoQueueDispatchManual模式允许驱动程序手工分发请求,类似于WDM的工作方式。
在WDM驱动程序中,I/O请求的取消是一个复杂难以理解的过程,开发人员必须有对内核深刻的理解才能正确处理I/O请求的取消。WDF框架支持内建的I/O请求取消处理,使得驱动程序处理取消I/O请求的工作大大简化。

3. WDF设备驱动程序的结构
与WDM驱动程序一样,WDF驱动程序得标准入口函数是DriverEntry。与WDM不同,WDF的DriverEntry只负责创建和初始化WDFDRIVER对象,告诉WDF框架处理增加新设备连接的回调函数。

NTSTATUS   DriverEntry(PDRIVER_OBJECT DriverObj, PUNICODE_STRING RegistryPath)
 {
      NTSTATUS code;
      WDF_DRIVER_CONFIG config;
      WDFDRIVER hDriver;
      // 初始化驱动配置结构,指定设备添加事件callback
 WDF_DRIVER_CONFIG_INIT_NO_CONSTRAINTS(&config, MyEvtDeviceAdd);
      // 创建WDFDRIVER对象
 code = WdfDriverCreate(DriverObj,
                               RegistryPath,
                               WDF_NO_OBJECT_ATTRIBUTES,
                               &config,    // 指向config结构的指针
                               NULL);      
      return(code);
 }


     每当有新设备连接到系统时,WDF框架自动调用EvtDeviceAdd设备添加callback。该回调函数初始化pnp和电源管理相关结构,设置相应的事件处理callbacks,然后创建WDFDEVICE对象和符号连接,初始化请求队列、中断处理等相关结构,设置相应的回调函数。


WDFSTATUS   MyEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
 {
      WDFSTATUS status = STATUS_SUCCESS;
      WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
      WDF_OBJECT_ATTRIBUTES objAttributes;
      WDFDEVICE device;
      PMY_DEVICE_CONTEXT devContext;
      WDF_IO_QUEUE_CONFIG ioCallbacks;
      WDF_INTERRUPT_CONFIG interruptConfig;
     // 初始化pnpPowerCallbacks ,设置与PnP和电源管理相关的事件回调函数
     WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
      pnpPowerCallbacks.EvtDevicePrepareHardware = MyEvtPrepareHardware;
      pnpPowerCallbacks.EvtDeviceReleaseHardware = MyEvtReleaseHardware;
      pnpPowerCallbacks.EvtDeviceD0Entry= MyEvtDeviceD0Entry;
     pnpPowerCallbacks.EvtDeviceD0Exit = MyEvtDeviceD0Exit;
      WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, pnpPowerCallbacks);
          // 创建设备对象,初始化相关的属性
        WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes);
       WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes,
                                             MY_DEVICE_CONTEXT);
        // 命名设备
 status = WdfDeviceInitUpdateName(DeviceInit, L"\\device\\WDFDEMO");
      if (!NT_SUCCESS(status))      return(status);
      status = WdfDeviceCreate(&DeviceInit, &objAttributes, &device);     
       if ( !NT_SUCCESS(status))      return(status);
      devContext = MyGetContextFromDevice(device);
 devContext->WdfDevice = device;
       // 创建符号连接
      status = WdfDeviceCreateSymbolicLink(device, L"\\DosDevices\\WDFDEMO");
      if (!NT_SUCCESS(status))      return(status);
      // 创建和初始化请求队列
      WDF_IO_QUEUE_CONFIG_INIT(&ioCallbacks, WdfIoQueueDispatchSerial,
                               WDF_NO_EVENT_CALLBACK,   WDF_NO_EVENT_CALLBACK);
 ioCallbacks.EvtIoDeviceControl = MyEvtDeviceControlIoctl;
 status = WdfDeviceCreateDefaultQueue(device,&ioCallbacks,
 WDF_NO_OBJECT_ATTRIBUTES,NULL);  
      if (!NT_SUCCESS(status))     return(status);
      // 创建和初始化中断对象,MyIsr和MyDpc分别是中断服务例程和DPC例程
 WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, FALSE,   MyIsr, MyDpc);
      interruptConfig.EvtInterruptEnable   = MyEvtInterruptEnable;//中断使能
     interruptConfig.EvtInterruptDisable = MyEvtInterruptDisable;//中断禁止
      status = WdfInterruptCreate(device, &interruptConfig,&objAttributes,
 &devContext->WdfInterrupt);
 return(status);
 }


WDF驱动程序下一步的工作就是编写各事件处理回调函数,当相应事件发生时,WDF框架会自动调用指定的回调函数进行处理。其中EvtDevicePrepareHardware回调函数在分配资源的时候被调用,框架将分配给设备的资源传递给回调函数,回调函数保存需要的资源,将共享内存映射到内核虚拟地址空间。与此对应的是EvtDeviceReleaseHardware回调函数,每当设备释放所占用的资源时,框架都将调用它。
EvtDeviceD0Entry 和 EvtDeviceD0Exit事件callbacks则分别在设备即将进入和离开D0电源状态时调用。EvtIoDeviceControl、EvtIoRead、EvtIoWrite等回调函数分别用来处理DeviceControl、Read、Write I/O请求。当框架获得一个I/O请求时,它首先确定该请求应该放入哪个请求队列。如果驱动程序没有提供指定的队列,WDF框架默认将请求放入缺省请求队列会自动调用对应的回调函数。然后,框架寻找处理该请求的回调函数,如果驱动程序提供了相应的callback,则调用它处理请求。对于没有指定回调函数的I/O请求,WDF调用EvtIoStart回调函数处理。如果EvtIoStart callback也不存在,框架将返回STATUS_NOT_SUPPORTED。
设备中断的管理由EvtInterruptEnable callback、EvtInterruptDisable callback、中断服务例程(ISR)和DpcForISr例程实现。WDF框架在调用EvtDeviceD0Entry callback和注册ISR后,通过调用EvtInterruptEnable回调函数使能设备中断;而EvtInterruptDisable回调函数则在设备离开D0状态,EvtDeviceD0Exit callback调用前获得调用,完成禁止设备中断的工作。此外,中断服务例程和DpcForIsr例程具体完成中断服务的功能,与WDM驱动程序相似。


--------------------------------------------分界线--------------------------------------------------------

Introduction to the WDF User?Mode Driver Framework
 Abstract
 The Windows Driver Foundation (WDF) is Microsoft’s next-generation driver model. WDF includes frameworks to support both user-mode and kernel-mode drivers, along with driver testing and verification tools. The user-mode driver framework (UMDF) component of WDF enables drivers for some types of devices to run in user mode instead of kernel mode.
 This paper provides an overview of the user-mode driver framework architecture, describes the advantages of user-mode drivers, and includes guidelines for determining whether to write a user-mode or kernel-mode driver.
 This information applies for the following operating systems:
        Microsoft Windows Vista?
        Microsoft® Windows® XP The current version of this paper is maintained on the Web at: 
        References and resources discussed here are listed at the end of this paper.
 Contents


百度百科介绍:http://baike.baidu.com/link?url=I7wlOW0o3fk5pGaaDYUYgEPPNaeUH-gdSO_B43KmZ404RynrXlUBteNdVOdpDl_C