Uso de elementos de trabajo de marco

Un elemento de trabajo es una tarea que realiza un controlador en una función de devolución de llamada de eventos EvtWorkItem . Estas funciones se ejecutan de forma asincrónica, en IRQL = PASSIVE_LEVEL, en el contexto de un subproceso de trabajo del sistema.

Los controladores basados en marcos suelen usar elementos de trabajo si una función EvtInterruptDpc o EvtDpcFunc , que se ejecuta en IRQL = DISPATCH_LEVEL, debe realizar un procesamiento adicional en IRQL = PASSIVE_LEVEL.

Es decir, un controlador puede usar elementos de trabajo si una función que se ejecuta en IRQL = DISPATCH_LEVEL debe llamar a una función que solo se pueda llamar en IRQL = PASSIVE_LEVEL.

Normalmente, la función de devolución de llamada EvtInterruptDpc o EvtDpcFunc de un controlador crea un objeto de elemento de trabajo y lo agrega a la cola de elementos de trabajo del sistema. Posteriormente, un subproceso de trabajo del sistema pone en cola el objeto y llama a la función de devolución de llamada EvtWorkItem del elemento de trabajo.

Controladores de ejemplo que usan elementos de trabajo

Los controladores basados en marcos de ejemplo que usan elementos de trabajo incluyen 1394, AMCC5933, PCIDRV y Toaster.

Configurar un elemento de trabajo

Para configurar un elemento de trabajo, el controlador debe:

  1. Cree el elemento de trabajo.

    El controlador llama a WdfWorkItemCreate para crear un objeto de elemento de trabajo e identificar una función de devolución de llamada EvtWorkItem que procesará el elemento de trabajo.

  2. Almacenar información sobre el elemento de trabajo.

    Normalmente, los controladores usan la memoria de contexto del objeto de elemento de trabajo para almacenar información sobre la tarea que debe realizar la función de devolución de llamada EvtWorkItem . Cuando se llama a la función de devolución de llamada EvtWorkItem , puede recuperar la información accediendo a esta memoria de contexto. Para obtener información sobre cómo asignar y acceder a la memoria de contexto, vea Espacio de contexto de objetos de marco.

  3. Agregue el elemento de trabajo a la cola de elementos de trabajo del sistema.

    El controlador llama a WdfWorkItemEnqueue, que agrega el elemento de trabajo del controlador a la cola de elementos de trabajo.

Cuando el controlador llama a WdfWorkItemCreate, debe proporcionar un identificador a un objeto de dispositivo de marco o a un objeto de cola de marco. Cuando el sistema elimina ese objeto, también elimina los elementos de trabajo existentes asociados al objeto . El objeto de elemento de trabajo se eliminará y se limpiará la devolución de llamada del elemento de trabajo asociado antes de invocar la devolución de llamada EvtCleanupCallback del objeto primario.

Para obtener más información sobre las reglas de limpieza de una jerarquía de objetos de marco, consulte Ciclo de vida de objetos de marco.

Uso de la función de devolución de llamada de Work-Item

Después de agregar el elemento de trabajo a la cola de elementos de trabajo, permanece en la cola hasta que un subproceso de trabajo del sistema esté disponible. El subproceso de trabajo del sistema quita el elemento de trabajo de la cola y, a continuación, llama a la función de devolución de llamada EvtWorkItem del controlador, pasando el objeto de elemento de trabajo como entrada.

Normalmente, la función de devolución de llamada EvtWorkItem realiza los pasos siguientes:

  1. Obtiene información proporcionada por el controlador sobre el elemento de trabajo accediendo a la memoria de contexto del objeto de elemento de trabajo.

  2. Realiza la tarea que especificó. Si es necesario, la función de devolución de llamada puede llamar a WdfWorkItemGetParentObject para determinar el objeto primario del elemento de trabajo.

  3. Llama a WdfObjectDelete para eliminar el objeto de elemento de trabajo o, si el controlador volverá a poner en cola el elemento de trabajo, indica que el identificador del elemento de trabajo ya está disponible para su reutilización.

La tarea que realiza la función de devolución de llamada de cada elemento de trabajo debe ser relativamente corta. El sistema operativo proporciona un número limitado de subprocesos de trabajo del sistema, por lo que el controlador puede impedir el rendimiento del sistema si usa funciones de devolución de llamada de elementos de trabajo para realizar tareas que requieren mucho tiempo.

Crear y eliminar elementos de trabajo

Los controladores pueden usar una de las dos técnicas siguientes para crear y eliminar elementos de trabajo:

  • Use cada elemento de trabajo una vez: cree el elemento de trabajo cuando lo necesite y elimínelo inmediatamente después de su uso.

    Esta técnica es útil para los controladores que requieren un uso poco frecuente (menos de una vez por minuto) de un pequeño número de elementos de trabajo.

    Por ejemplo, la función de devolución de llamada EvtInterruptDpc de un controlador puede llamar a WdfWorkItemCreate y, a continuación, WdfWorkItemEnqueue, y la función de devolución de llamada EvtWorkItem del elemento de trabajo puede llamar a WdfObjectDelete.

    Si el controlador sigue este escenario y su función de devolución de llamada EvtInterruptDpc recibe un valor devuelto STATUS_INSUFFICIENT_RESOURCES de WdfWorkItemCreate, el controlador debe poder posponer el trabajo necesario hasta que los recursos del sistema (normalmente memoria) estén disponibles.

  • Cree uno o varios elementos de trabajo que el controlador vuelva a poner en cola según sea necesario.

    Esta técnica es útil para los controladores que usan elementos de trabajo con frecuencia (más de una vez por minuto) o si la función de devolución de llamada EvtInterruptDpc del controlador no puede controlar fácilmente un valor devuelto STATUS_INSUFFICIENT_RESOURCES de WdfWorkItemCreate.

    El sistema no asigna un subproceso de trabajo a un elemento de trabajo hasta que el controlador llama a WdfWorkItemEnqueue. Por lo tanto, aunque los subprocesos de trabajo del sistema son un recurso limitado, la creación de elementos de trabajo al inicializar un dispositivo consume una pequeña cantidad de memoria, pero no afecta de otro modo al rendimiento del sistema.

    En los pasos siguientes se describe un escenario posible:

    1. La función de devolución de llamada EvtDriverDeviceAdd de un controlador llama a WdfWorkItemCreate para obtener un identificador de elemento de trabajo.
    2. La función de devolución de llamada EvtInterruptDpc del controlador crea una lista de acciones que la función de devolución de llamada EvtWorkItem debe realizar y, a continuación, llama a WdfWorkItemEnqueue, mediante el identificador del paso 1.
    3. La función de devolución de llamada EvtWorkItem del controlador realiza la lista de acciones y establece una marca para indicar que se ha ejecutado la función de devolución de llamada.

    Posteriormente, cada vez que se llama a la función de devolución de llamada EvtInterruptDpc del controlador, debe determinar si se ha ejecutado la función de devolución de llamada EvtWorkItem . Si la función de devolución de llamada EvtWorkItem no se ha ejecutado, la función de devolución de llamada EvtInterruptDpc no llama a WdfWorkItemEnqueue, porque el elemento de trabajo sigue en cola. En este caso, la función de devolución de llamada EvtInterruptDpc solo actualiza la lista de acciones de la función de devolución de llamada EvtWorkItem .

    Cada elemento de trabajo está asociado a un dispositivo o una cola. Cuando se quita el dispositivo o la cola asociados, el marco elimina todos los elementos de trabajo asociados, por lo que si usa esta técnica, el controlador no tiene que llamar a WdfObjectDelete.

Es posible que algunos controladores deban llamar a WdfWorkItemFlush para vaciar sus elementos de trabajo de la cola de elementos de trabajo. Para obtener un ejemplo de uso de WdfWorkItemFlush, consulte la página de referencia del método.

Si el controlador llama a WdfObjectDelete en un elemento de trabajo pendiente, el resultado depende del estado del elemento de trabajo:

Estado del elemento de trabajo Resultado
Creado pero no en cola El elemento de trabajo se limpia inmediatamente.
en cola La llamada a WdfObjectDelete espera hasta que el elemento de trabajo finaliza la ejecución y, a continuación, se limpia el elemento de trabajo.
Executing Si el controlador llama a WdfObjectDelete desde EvtWorkItem (en el mismo subproceso), WdfObjectDelete devuelve inmediatamente. Una vez finalizado EvtWorkItem , se limpiará el elemento de trabajo. De lo contrario, WdfObjectDelete espera a que EvtWorkItem finalice.