管理对象的生存期

警告

UMDF 2 是最新版本的 UMDF,取代了 UMDF 1。 所有新的 UMDF 驱动程序都应使用 UMDF 2 编写。 未向 UMDF 1 添加新功能,并且较新版本的 Windows 10 上对 UMDF 1 的支持有限。 通用 Windows 驱动程序必须使用 UMDF 2。

存档的 UMDF 1 示例可在 Windows 11 版本 22H2 - 2022 年 5 月驱动程序示例更新中找到。

有关详细信息,请参阅使用 UMDF 入门

UMDF 使用引用计数方案来管理 回调对象框架对象的生存期。

管理对Driver-Supplied回调对象的引用

在大多数情况下,驱动程序不需要保留对回调对象的引用。 如果回调对象接口的方法仅由框架和其生存期依赖于回调对象和回调对象的配对框架对象的对象调用,则驱动程序不必保留引用。 换句话说,驱动程序或框架可以安全地调用对象层次结构中较高位置的对象接口的方法。

管理对框架对象的引用

在 UMDF 中,常规 COM 生存期原则和特定于 WDF 的生存期模型决定了框架对象的生存期。 驱动程序必须满足这两个模型的条件,以便在适当时间从内存中释放框架对象。

COM 生存期管理

在 COM 中,调用方通常会在使用对象时保留对对象的引用,然后调用方在不再需要该对象时释放该引用。 但是,UMDF 驱动程序不需要保留对框架对象的引用。 事实上,驱动程序可以在驱动程序创建框架对象后立即释放框架对象引用。

例如,UMDF 示例在调用 IWDFDriver::CreateDevice 后释放设备对象。 虽然引用是提前释放的,但设备对象在删除设备之前会一直存在,因为 WDF 对象树会保留对它的引用。

由于 UMDF 跟踪对象树中的所有框架对象,因此驱动程序不需要保留对框架对象的引用。

但是,如果驱动程序保留对框架对象的引用,则驱动程序必须在不再需要该对象时释放该引用。 在驱动程序释放其引用之前,循环引用保持不变。 为了避免循环引用,驱动程序通常不应保留对框架对象的显式引用。

如果驱动程序必须保留对框架对象的引用,则驱动程序的回调对象还必须实现 IObjectCleanup 接口。 当驱动程序对框架对象调用 IWDFObject::D eleteWdfObject 时,框架对象将调用其相应的回调对象的 IObjectCleanup::OnCleanup 方法。 IObjectCleanup::OnCleanup 的实现必须释放对框架对象的引用,以使框架能够完成框架对象的拆解。

WDF 生存期管理

如果要创建允许重写默认父级的类型的对象,则应选择生存期与对象的生存期匹配的父级。 有关默认父对象以及驱动程序是否可以替代默认父对象的详细信息,请参阅 Framework Objects 中的表。

如果匹配对象生存期,框架在删除父对象时会删除对象。 如果与对象生存期不匹配,并且希望在删除默认父级之前删除该对象,则可以在不再需要该对象时通过调用 DeleteWdfObject 来显式删除该对象。

例如,如果创建新的请求对象,然后调用 IWDFDriver::CreateWdfMemory 为此请求创建内存对象,则可以将请求对象指定为新内存对象的父对象。 由于 WDF 在删除父对象时会删除子对象,因此驱动程序不需要调用 DeleteWdfObject 即可删除内存对象。

但是,如果没有父级的生存期与对象的生存期密切相关,并且如果希望在删除默认父级之前删除该对象,则必须使用显式删除。 例如,驱动程序可以创建多个在短时间内使用的请求对象。 在这种情况下,驱动程序可以通过在不再需要请求时显式删除请求来节省内存。

同样,如果创建的对象不允许重写默认父级,并且希望在删除默认父级之前删除该对象,驱动程序必须显式删除该对象。