首页 > 其他分享 >WDF驱动开发-工作项

WDF驱动开发-工作项

时间:2024-06-20 09:27:40浏览次数:20  
标签:调用 函数 WDF 工作 开发 EvtWorkItem 驱动 回调 驱动程序

工作项、线程和定时器是内核中用于执行长期任务的三种形态,其中工作项和线程本身没什么区别,只不过工作项对处理器的亲和性更好一些。工作项是驱动程序在 EvtWorkItem 事件回调函数中执行的任务。 这些函数在系统工作线程的上下文中以 IRQL = PASSIVE_LEVEL 异步运行。

如果以 IRQL = DISPATCH_LEVEL 运行的 EvtInterruptDpc 或 EvtDpcFunc 函数必须在 IRQL = PASSIVE_LEVEL 执行其他处理,则基于框架的驱动程序通常使用工作项。

换句话说,如果以 IRQL = DISPATCH_LEVEL 运行的函数必须调用只能在 IRQL = PASSIVE_LEVEL 调用的函数,驱动程序可以使用工作项。

通常,驱动程序的 EvtInterruptDpc 或 EvtDpcFunc 回调函数会创建一个工作项对象,并将其添加到系统的工作项队列中。 随后系统工作线程将对象取消排队,并调用工作项的 EvtWorkItem 回调函数。

设置工作项

若要设置工作项,驱动程序必须:

  • 创建工作项:驱动程序调用 WdfWorkItemCreate 来创建工作项对象并标识将处理工作项的 EvtWorkItem 回调函数;
  • 存储有关工作项的信息:通常,驱动程序使用工作项对象的上下文内存来存储 有关 EvtWorkItem 回调函数应执行的任务的信息。 调用 EvtWorkItem 回调函数时,它可以通过访问此上下文内存来检索信息; 
  • 将工作项添加到系统的工作项队列:驱动程序调用 WdfWorkItemEnqueue,它将驱动程序的工作项添加到工作项队列;

当驱动程序调用 WdfWorkItemCreate 时,它必须提供框架设备对象或框架队列对象的句柄。 当系统删除该对象时,它还会删除与该对象关联的任何现有工作项。 在调用父对象的 EvtCleanupCallback 回调之前,将释放工作项对象并清理其关联的工作项回调。

使用Work-Item回调函数

将工作项添加到工作项队列后,它将保留在队列中,直到系统工作线程变得可用。 系统工作线程从队列中删除工作项,然后调用驱动程序的 EvtWorkItem 回调函数,将工作项对象作为输入传递。

通常, EvtWorkItem 回调函数执行以下步骤:

  • 通过访问工作项对象的上下文内存,获取驱动程序提供的有关工作项的信息;
  • 执行指定的任务。 如有必要,回调函数可以调用 WdfWorkItemGetParentObject 来确定工作项的父对象;
  • 调用 WdfObjectDelete 以删除工作项对象,或者,如果驱动程序将重新排队工作项,则指示工作项的句柄现在可以重复使用;

每个工作项的回调函数执行的任务必须相对较短。 操作系统提供有限数量的系统工作线程,因此,如果驱动程序使用工作项回调函数执行耗时的任务,则可能会妨碍系统性能。

创建和删除工作项

驱动程序可以使用以下两种技术之一来创建和删除工作项:

1. 使用每个工作项一次:在需要时创建工作项,并在使用后立即将其删除。

此方法适用于需要很少使用 (频率低于每分钟一次的驱动程序) 的少量工作项。

例如,驱动程序的 EvtInterruptDpc 回调函数可以调用 WdfWorkItemCreate, 然后 WdfWorkItemEnqueue,工作项的 EvtWorkItem 回调函数可以调用 WdfObjectDelete。

如果驱动程序遵循此方案,并且其 EvtInterruptDpc 回调函数从 WdfWorkItemCreate 收到STATUS_INSUFFICIENT_RESOURCES返回值,则驱动程序必须能够推迟所需的工作,直到系统资源 (通常内存) 可用。

2. 创建驱动程序根据需要重新排队的一个或多个工作项。

对于使用工作项频繁 (每分钟) 一次以上的驱动程序,或者驱动程序的 EvtInterruptDpc 回调函数无法轻松处理 来自 WdfWorkItemCreate 的STATUS_INSUFFICIENT_RESOURCES返回值,此方法非常有用。

在驱动程序调用 WdfWorkItemEnqueue 之前,系统不会将工作线程分配给工作项。 因此,即使系统工作线程是有限的资源,在初始化设备时创建工作项会消耗少量内存,但不会影响系统性能。

以下步骤描述了一种可能的方案:

  • 驱动程序的 EvtDriverDeviceAdd 回调函数调用 WdfWorkItemCreate 以获取工作项句柄;
  • 驱动程序的 EvtInterruptDpc 回调函数创建 EvtWorkItem 回调函数必须执行的操作列表,然后使用步骤 1 中的句柄调用 WdfWorkItemEnqueue;
  • 驱动程序的 EvtWorkItem 回调函数执行操作列表,并设置一个标志以指示回调函数已运行;

随后,每次调用驱动程序的 EvtInterruptDpc 回调函数时,它都必须确定 EvtWorkItem 回调函数是否已运行。 如果 EvtWorkItem 回调函数尚未运行, 则 EvtInterruptDpc 回调函数不会调用 WdfWorkItemEnqueue,因为工作项仍处于排队状态。 在这种情况下, EvtInterruptDpc 回调函数仅更新 EvtWorkItem 回调函数的操作列表。

每个工作项都与设备或队列相关联。 删除关联的设备或队列时,框架会删除所有关联的工作项,因此,如果使用此技术,驱动程序不必调用 WdfObjectDelete。

一些驱动程序可能需要调用 WdfWorkItemFlush 以从工作项队列中刷新其工作项。

如果驱动程序对未完成的工作项调用 WdfObjectDelete ,则结果取决于工作项的状态:

工作项状态    结果
已创建但未排队立即清理工作项
已排队对 WdfObjectDelete 的调用将等待工作项完成执行,然后清理工作项
执行如果驱动程序从同一线程上的 EvtWorkItem 调用 WdfObjectDelete,则 WdfObjectDelete 将立即返回。 EvtWorkItem 完成后,将清理工作项。 否则, WdfObjectDelete 将等待 EvtWorkItem 完成。

标签:调用,函数,WDF,工作,开发,EvtWorkItem,驱动,回调,驱动程序
From: https://blog.csdn.net/m0_72813396/article/details/139756001

相关文章

  • 微信小程序开发中的推送通知与消息订阅【含代码示例】
    微信小程序开发中的推送通知与消息订阅【含代码示例】基础概念与作用推送通知(PushNotifications)消息订阅(MessageSubscription)技术实现与代码示例示例一:注册与配置推送权限示例二:发送模板消息示例三:处理用户点击通知事件功能使用思路与技巧个性化推送策略提升用户体验......
  • 微信小程序开发中的用户数据统计与分析【含代码示例】
    微信小程序开发中的用户数据统计与分析【含代码示例】基本概念与作用数据统计数据分析微信小程序数据统计方案1.微信官方统计工具2.第三方统计平台代码示例与实践示例一:使用微信官方统计API示例二:集成第三方统计SDK功能使用思路与技巧分析视角多样化数据驱动迭代实......
  • Android Java开发异步
    目录AndroidJava开发异步为什么需要异步编程?AsyncTask类异步编程的注意事项总结AndroidJava开发异步在Android应用程序中,异步编程是至关重要的,它可以确保应用的流畅性和响应性。在本文中,我们将探讨Android开发中的异步编程,以及如何使用Java语言进行异步操作。为什......
  • 学习笔记STMF4 TIMER定时器(使用开发板立创天空星STMF4)
    目录                                                #定时器的介绍             #怎么去理解定时器的预分频系数                                        ......
  • 【golang学习之旅】Go程序快速开始 & Go程序开发的基本注意事项
    系列文章【golang学习之旅】使用VScode安装配置Go开发环境【golang学习之旅】报错:adeclaredbutnotused【golang学习之旅】Go的基本数据类型【golang学习之旅】深入理解字符串string数据类型【golang学习之旅】gomodtidy【golang学习之旅】记录一次paniccase......
  • 移植案例与原理 - HDF驱动框架-OSAL
    为了提升驱动代码在不同内核子系统间的可复用能力,OpenHarmonyHDF(HardwareDriverFoundation)驱动框架提供了OSAL(OperatingSystemAbstractionLayer)操作系统抽象层接口。OSAL为驱动程序提供了任务、定时器、互斥锁、信号量等基础库相关接口,使驱动相关的实现不再依赖于具......
  • 使用C#开发OPC UA服务器
    OPC基金会提供了OPCUA.NET标准库以及示例程序,但官方文档过于简单,光看官方文档和示例程序很难弄懂OPCUA.NET标准库怎么用,花了不少时间摸索才略微弄懂如何使用,以下记录如何从一个控制台程序开发一个OPCUA服务器。安装Nuget包安装OPCFoundation.NetStandard.Opc.Ua主程序修......
  • Java项目开发中异步调用场景控制并发数
    场景项目基于SpringBoot搭建,默认使用TomcatWeb容器,对于每个HTTP请求,TomcatWeb容器会分配1个线程来处理请求。在pom.xml里查看依赖关系:spring-boot-starter-web添加了tomcat-embed-core依赖Tomcat线程池配置可在application.yml配置:server:tomcat:max-threads:5......
  • 【MT9669】GPIO IRQ功能在驱动中使用说明
    在MT9669的Linux Kernel中,驱动要如何实现中断操作呢?下面是对于非PM GPIO口实现IRQ的相应操作说明:1.在MT9669中对于GPIOIRQ的对应关系说明如下: 在bootable/bootloader/mboot-mtk/mboot/sboot/inc/M7642/board/BD_MT167B_10AT_MT5888_M7642.h中有如下内容:#definePADS_EX......
  • 【深度学习驱动流体力学】计算流体力学openfoam-paraview与python3交互
    目的1:配置ParaView中的PythonShell和Python交互环境ParaView提供了强大的Python接口,允许用户通过Python脚本来控制和操作其可视化功能。在ParaView中,可以通过View>PythonShell菜单打开PythonShell窗口,用于执行Python代码。要确保正确配置Python......