프레임워크 작업 항목 사용

작업 항목은 드라이버가 EvtWorkItem 이벤트 콜백 함수에서 수행하는 작업입니다. 이러한 함수는 IRQL = PASSIVE_LEVEL 시스템 작업자 스레드의 컨텍스트에서 비동기적으로 실행됩니다.

IRQL = DISPATCH_LEVEL 실행되는 EvtInterruptDpc 또는 EvtDpcFunc 함수가 IRQL = PASSIVE_LEVEL 추가 처리를 수행해야 하는 경우 프레임워크 기반 드라이버는 일반적으로 작업 항목을 사용합니다.

즉, IRQL = DISPATCH_LEVEL 실행되는 함수가 IRQL = PASSIVE_LEVEL 호출할 수 있는 함수를 호출해야 하는 경우 드라이버는 작업 항목을 사용할 수 있습니다.

일반적으로 드라이버의 EvtInterruptDpc 또는 EvtDpcFunc 콜백 함수는 작업 항목 개체를 만들고 시스템의 작업 항목 큐에 추가합니다. 그 후 시스템 작업자 스레드는 개체를 큐에서 제거하고 작업 항목의 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 내에서 WdfObjectDelete를 호출하면 WdfObjectDelete가 즉시 반환됩니다. EvtWorkItem이 완료되면 작업 항목이 정리됩니다. 그렇지 않으면 WdfObjectDelete 가 EvtWorkItem이 완료되기를 기다립니다.