共用方式為


使用 Framework 的工作項目

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

框架型驅動程式通常會使用工作專案,當函式 EvtInterruptDpcEvtDpcFunc 在 IRQL = DISPATCH_LEVEL 執行時,必須在 IRQL = PASSIVE_LEVEL 執行額外的處理。

換句話說,如果有一個函式在 IRQL = DISPATCH_LEVEL 執行而需要呼叫一個只能在 IRQL = PASSIVE_LEVEL 呼叫的函式,那麼驅動程式可以使用工作項目。

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

使用工作項目的範例驅動程式

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

設定工作項目

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

  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 回呼函式 STATUS_INSUFFICIENT_RESOURCES收到 WdfWorkItemCreate傳回值,則驅動程式必須能夠延後所需的工作,直到系統資源(通常是記憶體)變成可用為止。

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

    這項技術適用於經常使用工作項目的驅動程式(每分鐘超過一次),或者,如果驅動程式的 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 內部呼叫 WdfObjectDelete,則 WdfObjectDelete 會立即返回。 一旦 EvtWorkItem 完成,該工作項目將被清除。 否則,WdfObjectDelete 等候 EvtWorkItem 完成。