驱动程序模型:wddm2.0_编写一个简单的驱动

驱动程序模型:wddm2.0_编写一个简单的驱动WDF驱动程序开发1.引言设备驱动程序是硬件设备连接到计算机系统的软件接口,任何设备都必须有相应的驱动程序才能在计算机系统上正常工作。设备驱动程序的优劣直接关系到整个系统的性能和稳定性,因此,设计和开发稳定高效的驱动程序具有重要意义。WDF(WindowsDriverFoundation)是微软提出的下一代全新的驱动程序模型,它是在WDM(windowsDriverModel)…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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; // 初始化驱动配置结构,指定设备添加事件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电源状态时调用。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驱动程序相似。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/189615.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 战争星球online服务器维护中,打开战争星球Online:世界争霸提示网络异常或者连接不上…

    战争星球online服务器维护中,打开战争星球Online:世界争霸提示网络异常或者连接不上…

    2021年8月16日
    68
  • Java 基础练习题

    Java 基础练习题1.java类名命名规则答:1.大驼峰命名法2.不能以数字开头3.不能使用关键字,但是可以包含关键字4.数字.字母._,$5.见名知意2.java变量名(标识符)的命名规则和注意事项1.小驼峰命名法2.不能以数字开头3.不能使用关键字,但是可以包含关键字4.数字.字母._,$5.见名知意注意事项:1.相同作用域中不允许重复定义2.变量未经初始化,不允许使用3.一条语句可以定义多个相同类型的变量3.求成绩占总成绩的百分比doublescore=90;double

    2022年7月7日
    18
  • springboot事物oracle,SpringBoot 事务管理

    springboot事物oracle,SpringBoot 事务管理事务管理是项目中必不可少的一部分,使用SpringBoot时,可以很方便的配置和使用事务管理器。1.导入依赖当导入jdbc或者jpa依赖后,SpringBoot会自动分别注入DataSourceTransactionManager或JpaTransactionManager。所以我们不需要任何配置就可以使用@Transactional注解来进行事务的使用。我习惯使用jdbc,虽然Jpa有各种…

    2022年5月29日
    35
  • 一些人人的代替[通俗易懂]

    一些人人的代替[通俗易懂]人人影视:http://www.yyets.com/  丫丫下载站:http://www.yayaxz.com/ 人人影视国际版:http://yzys.tv/   字幕大家也不用担心,推几个网站 http://subom.net/ 2.http://www.opensubtitles.org/   3.http://subsce…

    2022年7月15日
    13
  • Java字符串匹配_获取字符串

    Java字符串匹配_获取字符串文章目录一、示例二、解释1.replace()方法2.replaceAll()方法3.replaceFirst()方法4.常用的字符列表一、示例如图,都是为了替换字符串s中的”(“符号,但三种匹配方法,有三种不同的效果及写法。二、解释1.replace()方法replace()方法没有用到正则表达式,但会匹配所有的参数并进行替换2.replaceAll()方法replaceAll()方法使用的是正则表达式来匹配,而括号在正则表达式中是特殊字符,所以需要用双斜杠来进行转义,同时会匹配所..

    2022年8月21日
    6
  • elasticsearch面试常问问题_面试题 谈谈你对加班的看法

    elasticsearch面试常问问题_面试题 谈谈你对加班的看法前言随着企业对近实时搜索的迫切需求,Elasticsearch受到越来越多的关注,无论是阿里、腾讯、京东等互联网企业,还是平安、顺丰等传统企业都对Elasticsearch有广泛的使用,但是在Elasticsearch6.8发布以前,大部分Elasticsearch功能都是付费的,开源版本的Elasticsearch在集群管控方面能力有限,鉴于此,通用的实施方案就是给Elasticsearch添加一层网关,从而实现对Elasticsearch的管控。全套Java面试资料白嫖:

    2025年11月5日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号