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

WDF(Windows Driver Foundation)是微软提出的下一代全新的驱动程序模型,它是在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;// 初始化驱动配置结构,指定设备添加事件callbackWDF_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电源状态时调用。EvtIoDeviceControlEvtIoReadEvtIoWrite等回调函数分别用来处理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驱动程序相似。

WDF模型驱动程序开发相关推荐

  1. 从零开始学习Windows WDF驱动程序开发

    摘要:本文通过简单的例子和精简的说明,带你快速了解和掌握基于WDF架构的Windows驱动程序的开发过程.WDF自带的文档非常详细而且冗长,读者需要一定的编程基础和英语水平,再加上一定的努力,才能看明 ...

  2. 谈WDM与WDF (windows驱动开发)

    转载自http://yinaiyun52.blog.163.com/blog/static/36251574200826112436776/ WDF驱动模型 如所周知,自Windows 2000开始, ...

  3. 《Win7设备驱动程序开发》学习笔记

    <Windows 7 设备驱动程序开发>是美国Ronald D. Reeves著的一本关于WDF模型的Windows 驱动程序开发教程,适用于Win7和Win10.本文我学习该书的一些笔记 ...

  4. poll接口《来自Linux驱动程序开发实例》

    您所在的位置:读书频道 > 操作系统 > Linux > 1.2.7 poll接口 1.2.7 poll接口 2012-05-22 13:38 冯国进 机械工业出版社 我要评论(0) ...

  5. 异步通知《来自Linux驱动程序开发实例》

    您所在的位置:读书频道 > 操作系统 > Linux > 1.2.8 异步通知 1.2.8 异步通知 2012-05-22 13:38 冯国进 机械工业出版社 我要评论(0) 字号: ...

  6. 基于HDF的LED驱动程序开发(2)

    引言 本文以小熊派BearPi-HM_Micro_small开发板上的一个LED灯为例,介绍如何基于HDF框架开发一个外设的驱动程序. 在阅读本文之前,建议大家先阅读:<OpenHarmony驱 ...

  7. 基于HDF的LED驱动程序开发(1)

    引言 本文以小熊派BearPi-HM_Micro_small开发板上的一个LED灯为例,介绍如何基于HDF框架开发一个外设的驱动程序. 在阅读本文之前,建议大家先阅读:<OpenHarmony驱 ...

  8. VxWorks设备驱动程序开发指南---驱动程序的分类

    8D Spaces Reliability & Stability & Efficiency 目录视图 摘要视图 订阅 VxWorks设备驱动程序开发指南(三)---驱动程序的分类 2 ...

  9. VxWorks驱动程序开发指南--驱动程序的组织结构

    8D Spaces Reliability & Stability & Efficiency 目录视图 摘要视图 订阅 VxWorks驱动程序开发指南(四)--驱动程序的组织结构 20 ...

最新文章

  1. ORB_SLAM2帧Frame
  2. 微信公众号中ip白名单用谁的ip
  3. RAC IP 地址修改
  4. Core Location :⽤用于地理定位
  5. Redo Log 和Checkpoint not complete
  6. h-bulider怎么搭建php环境,使用Apache+Dreamweaver(或者H-builder)搭建php開發環境
  7. 因未能提交年度报告 瑞幸咖啡收到纳斯达克退市通知
  8. Mac终端文件类型显示不同颜色
  9. oracle-00028,Oracle 10g錯誤:「ORA-00028:您的會話已被終止」
  10. oracle9i怎样管理数据,数据库教程
  11. [原创]Linux系统启动过程分析
  12. android pickerview 多行,Android仿ios条件选择器pickerview
  13. mysql 安装版本选择_选择要安装的MySQL版本
  14. uchome 不用每次都更新缓存的方法
  15. 5G消息应用号推荐|官方种草清单第六期
  16. 浅谈:6sigma与Minitab_北京八方在线Minitab代理商
  17. 体验腾讯云区块链服务平台TBaaS
  18. 用OpenStack搭建简单的云平台并启动云主机
  19. 将图片转化为数据储存
  20. html中怎么设置渐变颜色设置,css中渐变色怎么设置

热门文章

  1. 【基础篇】详解Zookeeper客户端Curator
  2. 五证 两书 三表
  3. php和按键精灵,按键精灵的脚本 - 对于重复动作(含键盘鼠标)太好用了
  4. 人工智能系统中有哪些有前途的研究方向?
  5. 政务云存储 备份方案_在线云备份对于业务解决方案有多重要?
  6. 初始计算机安装安全系统标准化流程SOP文档
  7. 全志H6芯片方案OrangePi 3 LTS连接USB摄像头的操作方法(安卓镜像)
  8. 662k稳压芯片电路图,线性稳压芯片
  9. java中如何创建字符串数组
  10. 易语言 超级列表框的索引 是从0开始还是1开始的