使用 Framework 工作專案

工作專案是驅動程式在EvtWorkItem事件回呼函式中執行的工作。 這些函式會在系統背景工作執行緒的內容中,以非同步方式在 IRQL = PASSIVE_LEVEL執行。

如果 EvtInterruptDpcEvtDpcFunc 函式在 IRQL = DISPATCH_LEVEL執行,架構型驅動程式通常會使用工作專案,則必須在 IRQL = PASSIVE_LEVEL執行其他處理。

換句話說,如果在 IRQL = DISPATCH_LEVEL執行的函式必須呼叫只能在 IRQL = PASSIVE_LEVEL呼叫的函式,則驅動程式可以使用工作專案。

一般而言,驅動程式的 EvtInterruptDpcEvtDpcFunc 回呼函式會建立工作專案物件,並將它新增至系統的工作專案佇列。 接著,系統背景工作執行緒會清除物件佇列,並呼叫工作專案的 EvtWorkItem 回呼函式。

使用工作專案的範例驅動程式

使用工作專案的範例架構驅動程式包括 1394、AMCC5933、PCIDRV 和 Toaster。

設定工作專案

若要設定工作專案,您的驅動程式必須:

  1. 建立工作專案。

    您的驅動程式會呼叫 WdfWorkItemCreate 來建立工作專案物件,並識別將處理工作專案的 EvtWorkItem 回呼函式。

  2. 儲存工作專案的相關資訊。

    一般而言,驅動程式會使用工作專案物件的內容記憶體來儲存 EvtWorkItem 回呼函式應該執行之工作的相關資訊。 呼叫 EvtWorkItem 回呼函式時,可以藉由存取此內容記憶體來擷取資訊。 如需如何配置和存取內容記憶體的資訊,請參閱 Framework 物件內容空間

  3. 將工作專案新增至系統的工作專案佇列。

    您的驅動程式會呼叫 WdfWorkItemEnqueue,將驅動程式的工作專案新增至工作專案佇列。

當您的驅動程式呼叫 WdfWorkItemCreate時,它必須提供架構裝置物件或架構佇列物件的控制碼。 當系統刪除該物件時,也會刪除與 物件相關聯的任何現有工作專案。 將會處置工作專案物件,並在叫用父物件的 EvtCleanupCallback 回 呼之前清除其相關聯的工作專案回呼。

如需架構物件階層清除規則的詳細資訊,請參閱 Framework 物件生命週期

使用Work-Item回呼函式

工作專案新增至工作專案佇列之後,它會保留在佇列中,直到系統背景工作執行緒變成可用為止。 系統背景工作執行緒會從佇列中移除工作專案,然後呼叫驅動程式的 EvtWorkItem 回呼函式,並將工作專案物件當做輸入傳遞。

一般而言, EvtWorkItem 回呼函式會執行下列步驟:

  1. 藉由存取工作專案物件的內容記憶體,以取得工作專案的相關資訊。

  2. 執行您指定的工作。 如有必要,回呼函式可以呼叫 WdfWorkItemGetParentObject 來判斷工作專案的父物件。

  3. 呼叫 WdfObjectDelete 以刪除工作專案物件,或者,如果驅動程式將重新佇列工作專案,表示工作專案的控制碼現在可供重複使用。

每個工作專案回呼函式執行的工作必須相對短。 作業系統提供有限的系統背景工作執行緒數目,因此,如果驅動程式使用工作專案回呼函式來執行耗時的工作,您的驅動程式可能會阻礙系統效能。

建立和刪除工作專案

驅動程式可以使用下列兩種技術之一來建立和刪除工作專案:

  • 使用每個工作專案一次:當您需要工作專案時建立工作專案,並在使用後立即刪除它。

    這項技術適用于需要不常使用的驅動程式, (少於每分鐘) 少量工作專案的一次。

    例如,驅動程式的 EvtInterruptDpc 回呼函式可以呼叫 WdfWorkItemCreate ,然後 WdfWorkItemEnqueue,而工作專案的 EvtWorkItem 回呼函式可以呼叫 WdfObjectDelete

    如果您的驅動程式遵循此案例,而且其 EvtInterruptDpc 回呼函式收到 來自 WdfWorkItemCreate的STATUS_INSUFFICIENT_RESOURCES傳回值,則驅動程式必須能夠延後所需的工作,直到系統資源 (通常可用的記憶體) 為止。

  • 視需要建立一或多個工作專案,讓驅動程式重新排入佇列。

    這項技術對於經常使用工作專案 (頻率超過每分鐘) 一次的驅動程式很有用,或者,如果驅動程式的 EvtInterruptDpc 回呼函式無法輕易地處理 WdfWorkItemCreate的STATUS_INSUFFICIENT_RESOURCES傳回值。

    在驅動程式呼叫 WdfWorkItemEnqueue之前,系統不會將背景工作執行緒配置給工作專案。 因此,即使系統背景工作執行緒是有限的資源,在初始化裝置時建立工作專案會耗用少量的記憶體,但不會影響系統效能。

    下列步驟描述可能的案例:

    1. 驅動程式的 EvtDriverDeviceAdd 回呼函式會呼叫 WdfWorkItemCreate 以取得工作專案控制碼。
    2. 驅動程式的 EvtInterruptDpc 回呼函式會建立 EvtWorkItem 回呼函式必須執行的動作清單,然後使用步驟 1 的控制碼呼叫 WdfWorkItemEnqueue
    3. 驅動程式的 EvtWorkItem 回呼函式會執行動作清單,並設定旗標來指出回呼函式已執行。

    之後,每次呼叫驅動程式的 EvtInterruptDpc 回呼函式時,都必須判斷 EvtWorkItem 回呼函式是否已執行。 如果 EvtWorkItem 回呼函式尚未執行, EvtInterruptDpc 回呼函式不會呼叫 WdfWorkItemEnqueue,因為工作專案仍然排入佇列。 在此情況下, EvtInterruptDpc 回呼函式只會更新 EvtWorkItem 回呼函式的動作清單。

    每個工作專案都與裝置或佇列相關聯。 移除相關聯的裝置或佇列時,架構會刪除所有相關聯的工作專案,因此如果您使用這項技術,驅動程式就不需要呼叫 WdfObjectDelete

幾個驅動程式可能需要呼叫 WdfWorkItemFlush ,從工作專案佇列排清其工作專案。 如需 WdfWorkItemFlush的範例用法,請參閱方法的參考頁面。

如果驅動程式在未完成的工作專案上呼叫 WdfObjectDelete ,結果會取決於工作專案的狀態:

工作項目狀態 結果
已建立但未排入佇列 工作專案會立即清除。
已排入佇列 呼叫 WdfObjectDelete 會等候工作專案完成執行,然後清除工作專案
執行中 如果驅動程式在相同的執行緒) 上從EvtWorkItem (內呼叫WdfObjectDeleteWdfObjectDelete會立即傳回。 EvtWorkItem完成後,將會清除工作專案。 否則, WdfObjectDelete 會等候 EvtWorkItem 完成。