chapter 5.5: 对象层次及生命周期

KMDF和UMDF都使用引用计数,所有的对象都有引用计数:

    UMDF使用AddRef和Release来管理引用计数;

    KMDF使用WdfObjectReferenceXxx和WdfObjectDereferenceXxx维护引用计数

对象层次:

    

    如图,驱动对象是根,其它都是它的后代。设备总是驱动的儿子,queue通常是设备的儿子,也可能是a later descendant

    由framework构建及维护internal object tree

注意:驱动创建对象时,要正确设置父对象

    默认父对象为驱动

   若memory object只在I/O request,或者I/O target中用,需要设置父对象为他们

当对象被删除时,framework会首先调用最近一层子对象的cleanup callback,再调用自己的

driver通常不持有自己创建对象的reference,但是对要保证valid的对象时,需要持有reference,但是在删除那些对象时,需要释放reference(实现对象的cleanup callback)

名词解释:

    destruction:driver调用framework来删除对象时,最终会导致对象的destruction。第一步就是dispose对象的儿子(调用它们的cleanup callback)。dispose后,reference仍被child持有。当对象的最后一个reference移除后,framework调用对象的deletion callback,最终destroy对象。


UMDF对象层次

 

注意虚线,可以根据需要设置parent

当reference的计数为0时,可以调用IWDFObject::DeleteWdfObject

驱动在使用完pointer后需要调用Release:

可以对object的IUnknown 调用AddRef和Release(通常是不需要的),但若driver使用了object的reference,必须实现IObjectCleanup::OnCleanup接口

OnCleanup解决了COM的circular reference问题,用external event来打破circular

避免circular reference:使用弱引用(不增加引用计数)


KMDF对象层次


图中表示了parent chain关系:例如WDFDEVICE可以成为WDFQUEUE的曾祖父

若KMDF调用了删除了一个object方法,KMDF仅仅对object做一个标记,直到object的reference count到0时才会释放object占用的内存

KMDF driver只有在要保证一个object可用时才要显式管理object的reference,而且必须在删除object前在cleanup callback中调用WdfObjectDereference。


Object Deletion

触发deletion:

    1.object 的父亲被删除

    2.driver显式调用删除object方法:UMDF,IWDFObject::DeleteWdfObject; KMDF,WdfObjectDelete

framework和driver都可以控制删除,下表为driver是否可以删除一种object(只有允许被driver删除并且在driver控制之下的object能被删除):

Object

UMDF

KMDF

Child list

Not applicable

No

Collection

Not applicable

Yes

Device

No

No, except for control device objects and PDOs in a certain state

DMA common buffer

Not applicable

Yes

DMA enabler

Not applicable

Yes

DMA transaction

Not applicable

Yes

DPC

Not applicable

Yes

Driver

No

No

Driver-created file

Yes

Yes

File

No

No

Base or Generic object

Yes, if created by the driver

Yes, if created by the driver

I/O queue

No, for default I/O queue Yes, for other queues

Yes

I/O request

No, if created by the framework Yes, if created by the driver

No, if created by the framework Yes, if created by the driver

I/O target

No, for the default I/O target Yes, for all other targets

No, for the default I/O target Yes, for all other targets

Interrupt

Not applicable

No

Lookaside list

Not applicable

Yes

Memory

No, if created by the framework Yes, if created by the driver

No, if created by the framework Yes, if created by the driver

Named property store

No

Not applicable

Registry key

Not applicable

Yes

Resource list

Not applicable

No

Resource range list

Not applicable

Yes

Resource requirements list

Not applicable

No

String

Not applicable

Yes

Synchronization: spin lock

Not applicable

Yes

Synchronization: wait lock

Not applicable

Yes

Timer

Not applicable

Yes

USB device

No, for the default target Yes, for all other targets

Yes

USB interface

No, for the default target Yes, for all other targets

No

USB pipe

No, for the default target Yes, for all other targets

No

WMI instance

Not applicable

Yes

WMI provider

Not applicable

No

Work item

Not applicable

Yes

framework控制着大多数object及生命周期,如device object和default I/O target object,framework会在一处device时自动删除它们

只有在driver具有object时,driver才能显式地删除object。

当driver调用delete方法时,framework的行为:

    1.在callback object的interface上释放引用(UMDF only)

    2.无论reference count多少,先调用object的cleanup callback函数

    3.递减reference count

    4.标记object为delete

    5.当reference count为0时,删除object,并从object tree中移除

若driver未显式delete object,framework在它的parent被删除时删除该object

driver不能调用由framework控制的object的删除方法,否则:

    UMDF中,driver stop with error

    KMDF中,system bug check


Cleanup Callbacks

任何对象都支持

在删除object(或其parent)前,framework调用cleanup callback

cleanup的行为:释放任何object维护的outstanding references;释放object被分配的资源;做任何在deleted前需要的操作。

UMDF:callback object的IObjectCleanup interface的OnCleanup方法

KMDF:EvtCleanupCallback,在删除时且递减ref count前调用,该callback在创建object的attrivutes structure中注册。


Destroy Callbacks

driver可以实现一个destroy callback替换或附加到cleanup callback中

UMDF:

    UMDF没有destroy callback,在ref count到0时自动析构对象(行为和destroy一样)

    driver可以释放它对object分配的资源,但是无法决定在framework中删除它。

KMDF:

    EvtDestroyCallback,注册在attrivutes structure中

    调用顺序:对object及其所有parent 的cleanup callback完成(return),ref count变为0,然后是destroy callback,最后delete object


UMDF Object Deletion

driver创建的I/O request object通常是UMDF driver需要显式delete的

例子表示Fx2_Driver创建、发送和删除request(completion callback),

    在IWDFRequestCallbackRequestCompletion::OnCompletion中调用IWDFObject::DeleteWdfObject的例子(Device.cpp)

VOID CMyDevice::OnCompletion(
    IWDFIoRequest*                 FxRequest,
    IWDFIoTarget*                  pIoTarget,
    IWDFRequestCompletionParams*   pParams,
    PVOID                          pContext
    )
{
    . . . //Code omitted
    HRESULT hrCompletion = pParams->GetCompletionStatus();
    if (FAILED(hrCompletion)) {
        m_InterruptReadProblem = hrCompletion;
    } else  {

        // Get the returned parameters and other information
        . . . //Code omitted
    }
    FxRequest->DeleteWdfObject();
    . . . //Code omitted
}

driver要在DeleteWdfObject操作之前获取到所有信息,因为delete后,driver无法访问object了


KMDF Object Deletion

删除YourObject步骤:

    1.调用object tree中YourObject最远端后代的EvtCleanupCallback (用来释放显式的ref)

    2.重复1.直到YourObject的EvtCleanupCallback

    3.按相同顺序遍历tree,移除framework对object的reference。若counter到0,调用EvtDestroyCallback方法,最后释放分配到object和context area的内存

*不保证同一级的子孙调用cleanup的顺序

*framework精细地完成了同时在不同线程上的object的删除方法,通过一个driver-global dispose list完成

----KMDF中调用EvtCleanupCallback顺序---

依据层次删除object时能保证parent的存在,但driver显式调用object的EvtCleanupCallback时,无法保证父亲仍然存在。

一些对象的EvtCleanupCallback可以在PASSIVE_LEVEL或DISPATCH_LEVEL级别调用,但是下列对象只能在PASSIVE_LEVEL级别中调用:

WDFDEVICE

WDFQUEUE

WDFDPC

WDFSTRING

WDFIOTARGET

WDFTIMER

WDFLOOKASIDE objects that allocate paged pool

WDFWORKITEM

WDFMEMORY objects that contain paged pool

 

当objcet要等待某事完成或者访问了paged内存时,需要cleanup运行在PASSIVE_LEVEL中。

object的cleanup在DISPATCH_LEVEL中时,KMDF会把PASSIVE_LEVEL的任务推迟并放入一个work item,KMDF为每个device object维护一个work item,按顺序调用cleanup

需要在PASSIVE_LEVEL中cleanup的object不一定必须在PASSIVE_LEVEL中create。

    WDFWORKITEM, WDFTIMER, WDFDPC, 和 WDFQUEUE,以及使用了nonpaged pool的WDFMEMORY和WDFLOOKASIDE能在DISPATCH_LEVEL中创建。

    使用paged pool的WDFMEMORY和WDFLOOKASIDE,以及WDFDEVICE, WDFIOTARGET, WDFCOMMONBUFFER, WDFKEY, WDFCHILDLIST, WDFSTRING不能在DISPATCH_LEVEL中创建。

例外:Completed I/O request

    在I/O request object的子对象中不能有任何需要在PASSIVE_LEVEL中运行cleanup的对象

    由于IRP要尽快完成,若I/O request object有子对象timer object,KMDF会先完成IRP,删除I/O request object,在调用PASSIVE_LEVEL中的timer object的cleanup,导致出现父对象先被释放的错误

-----KMDF调用EvtDestroyCallback的顺序----

在cleanup和ref counter到0后才会调用Destroy

destroy可以不遵循先子后父顺序

destroy callback能访问object context area,但不能访问object的任何方法

KMDF不能保证调用destroy的IRQL级别

Echo的Driver.c的object deletion例子:

NTSTATUS status;
WDFSTRING string;
WDF_DRIVER_VERSION_AVAILABLE_PARAMS ver;
status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &string);
if (!NT_SUCCESS(status)) {
    . . .//Code omitted
}
status = WdfDriverRetrieveVersionString(WdfGetDriver(), string);
if (!NT_SUCCESS(status)) {
    . . .//Code omitted
}
. . .//Code omitted
WdfObjectDelete(string);
string = NULL; // To avoid referencing a deleted object.
图解:对string调用WdfObjectDelete


    



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值