Wdf框架之WdfObject状态机(1)

    "WDF对象有共同的根....共同的头部(WDF_OBJECT)..WDF_OBJECT对象中包含了这样一些基本信息:对象类型(Type),对象长度(Len),引用计数,指向Parent对象和子对象列表的指针等"----引自<竹林蹊径-深入浅出Windows驱动开发> P57。诚如按作者所说,source insight(下文简称SI)给出的引用关系图反应出FxDriver类中的确包含WDF_OBJECT结构(FxDriver类派生自FxObject类)。

    这篇文章并不是研究WDF对象的继承关系,只是借由FxDriver和FxObject引出本文的主题----WDF对象状态机。可是,为什么我们需要分析WDF对象状态机?大家是否记得在创建WDF框架对象时,可能需要为WDF对象指定WDF_OBJECT_ATTRIBUTES属性并设置EvtCleanupCallback/EvtDestroyCallback回调函数?当框架调用WdfObjectDereference减少引用计数时,会调用EvtCleanupCallback回调函数;更重要的是,当调用WdfObjectDelete时,会同时自子对象开始向父对象依次调用EvtCleanupCallback/EvtDestroyCallback,并最终释放WdfObject对象。为了实现上诉目标,WDF框架采用一种相对复杂的状态机机制,记录WdfObject对象从调用WdfObjectCreate时,开始进入状态机;调用operate::delete时,离开状态机及中间各个状态的迁移。本文的立意就是分析各状态之间的迁移~

    我们以WdfDriverCreate为例,从调用WdfObjectCreate函数,也就是创建WdfObject进入状态机开始。

_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFEXPORT(WdfDriverCreate)(
    PWDF_DRIVER_GLOBALS DriverGlobals,
    MdDriverObject DriverObject,
    PCUNICODE_STRING RegistryPath,
    PWDF_OBJECT_ATTRIBUTES DriverAttributes,
    PWDF_DRIVER_CONFIG DriverConfig,
    WDFDRIVER* Driver
    )
{
    //...
    // FxDriver stores the driver wide configuration
    FxInitialize(pFxDriverGlobals, DriverObject, RegistryPath, DriverConfig);
    // FxDriver stores the driver wide configuration
    pDriver = new(pFxDriverGlobals, DriverAttributes)
        FxDriver(DriverObject, DriverConfig, pFxDriverGlobals); 
    //...
}
由于FxDriver类及其父类FxNonPagedObject都没有重载operate new操作符,他们的公共基类FxObject重载了operate new操作符,因此上面的代码会进入公共基类的FxObject::operate new函数:
virtual
    ~FxObject(
        VOID
        );
    PVOID
    __inline
    operator new(
        __in size_t Size,
        __in PFX_DRIVER_GLOBALS FxDriverGlobals,
        __in FxObjectType Type
        );

等等,是不是觉得参数数量对不上?咋一看,operate new有3个参数,在WdfDriverCreate中调用new操作符时只传了2个参数。其实,第一个参数Size由编译器在编译阶段计算出大小并传给operate::new(参考<竹林蹊径 第六章 内核驱动c++编程 第6.1.2节>)。调用operate::new操作符只是根据FxDriver对象的大小分配相应的内存,之后会调用FxDriver::FxDriver()构造函数初始化刚分配的内存块:

FxDriver::FxDriver(
    __in MdDriverObject     ArgDriverObject,
    __in PWDF_DRIVER_CONFIG DriverConfig,
    __in PFX_DRIVER_GLOBALS FxDriverGlobals
    ) :
    FxNonPagedObject(FX_TYPE_DRIVER, sizeof(FxDriver), FxDriverGlobals), /*调用基类构造函数*/
    m_DriverObject(ArgDriverObject), /*初始化*FxDriver!m_DriverObject成员/
    m_CallbackMutexLock(FxDriverGlobals) /*初始化FxDriver!m_CallbackMutexLock成员*/
{/*FxDriver的构造函数*/}
FxDriver构造函数将m_DriverObject初始化为DriverEntry的参数,然后调用基类FxNonPagedObject::FxNonPagedObject()构造函数:

class FxNonPagedObject : public FxObject
{
public:
    FxNonPagedObject(
        __in WDFTYPE Type,
        __in USHORT Size,
        __in PFX_DRIVER_GLOBALS FxDriverGlobals
        ) :
        FxObject(Type, Size, FxDriverGlobals)
    {}
}
不过FxNonPagedObject::FxNonPagedObject()构造函数并没有做什么,只是把传入的参数原封不动的传给它的基类构造函数FxObject::FxObject();
FxObject::FxObject(
    __in WDFTYPE Type,
    __in USHORT Size,
    __in PFX_DRIVER_GLOBALS FxDriverGlobals
    ) :
    m_Type(Type),
    m_ObjectSize((USHORT) WDF_ALIGN_SIZE_UP(Size, MEMORY_ALLOCATION_ALIGNMENT)),
    m_Globals(FxDriverGlobals)
#if FX_CORE_MODE==FX_CORE_USER_MODE        
#ifndef INLINE_WRAPPER_ALLOCATION
    ,m_COMWrapper(NULL)
#endif
#endif
{
//重点出现了
    Construct(FALSE);
}
FxObject::FxObject() 构造函数将FxObject!m_Globals初始化为WDF框架驱动的全局变量pFxDriverGlobals。
    上面简单捋了一下构造函数调用链,现在开始正题,设置WdfObject状态标志。
VOID
    __inline
    FxObject::Construct(
        __in BOOLEAN Embedded
        )
    {
        m_Refcnt = 1;
        m_ObjectState = FxObjectStateCreated; //设置状态机
        m_ObjectFlags = 0;
        m_ParentObject = NULL;

        InitializeListHead(&m_ChildListHead);
        InitializeListHead(&m_ChildEntry);
        m_DisposeSingleEntry.Next = NULL;

        m_DeviceBase = NULL;

        VerifyConstruct(m_Globals, Embedded);
    }
Construct中设置m_ObjectState为 FxObjectStateCreated,至此,WdfObject正式被状态机管理。

这一篇比较简单,后面将分析调用WdfObjectDelete时,状态迁移,这是一个艰难的旅途。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值