Partilhar via


Usando itens de trabalho do Framework

Um item de trabalho é uma tarefa que um driver executa em uma função de retorno de chamada de evento EvtWorkItem . Essas funções são executadas de forma assíncrona, em IRQL = PASSIVE_LEVEL, no contexto de um thread de trabalho do sistema.

Os drivers baseados em framework geralmente usam itens de trabalho se uma função EvtInterruptDpc ou EvtDpcFunc, que é executada em IRQL = DISPATCH_LEVEL, precisa realizar processamento adicional em IRQL = PASSIVE_LEVEL.

Em outras palavras, um driver pode usar itens de trabalho se uma função que é executada em IRQL = DISPATCH_LEVEL deve chamar uma função que pode ser chamada apenas em IRQL = PASSIVE_LEVEL.

Normalmente, a função de retorno de chamada EvtInterruptDpc ou EvtDpcFunc de um driver cria um objeto de item de trabalho e o adiciona à fila de itens de trabalho do sistema. Posteriormente, um thread de trabalho do sistema coloca o objeto em fila e chama a função de retorno de chamada EvtWorkItem do item de trabalho.

Controladores de exemplo que usam itens de trabalho

Exemplos de drivers baseados em estrutura que usam itens de trabalho incluem 1394, AMCC5933, PCIDRV e Torradeira.

Configurando um item de trabalho

Para configurar um item de trabalho, o seu driver deve:

  1. Crie o item de trabalho.

    Seu driver chama WdfWorkItemCreate para criar um objeto de item de trabalho e identificar uma função de retorno de chamada EvtWorkItem que processará o item de trabalho.

  2. Armazene informações sobre o item de trabalho.

    Normalmente, os drivers usam a memória de contexto do objeto de item de trabalho para armazenar informações sobre a tarefa que a função de retorno de chamada EvtWorkItem deve executar. Quando a função de retorno de chamada EvtWorkItem é chamada, ela pode recuperar as informações acessando essa memória de contexto. Para obter informações sobre como alocar e acessar a memória de contexto, consulte Espaço de contexto de objeto do Framework.

  3. Adicione o item de trabalho à fila de itens de trabalho do sistema.

    O seu controlador chama WdfWorkItemEnqueue, o que adiciona o item de trabalho do controlador à fila de itens de trabalho.

Quando o driver chama WdfWorkItemCreate, ele deve fornecer um identificador para um objeto de dispositivo do framework ou um objeto de fila do framework. Quando o sistema exclui esse objeto, ele também exclui todos os itens de trabalho existentes associados ao objeto. O objeto de item de trabalho será descartado e seu retorno de chamada de item de trabalho associado será limpo antes que o retorno de chamada EvtCleanupCallback do objeto pai seja invocado.

Para saber mais sobre as regras de limpeza para uma hierarquia de objetos da estrutura, veja Ciclo de vida do objeto da estrutura.

Usando a função de retorno de chamada Work-Item

Depois que o item de trabalho tiver sido adicionado à fila de itens de trabalho, ele permanecerá na fila até que um thread de trabalho do sistema fique disponível. O thread de trabalho do sistema remove o item de trabalho da fila e, em seguida, chama a função de retorno de chamada EvtWorkItem do driver, passando o objeto de item de trabalho como entrada.

Normalmente, a função de retorno de chamada EvtWorkItem executa as seguintes etapas:

  1. Obtém informações fornecidas pelo driver sobre o item de trabalho acessando a memória de contexto do objeto de item de trabalho.

  2. Executa a tarefa que você especificou. Se necessário, a função de retorno de chamada pode chamar WdfWorkItemGetParentObject para determinar o objeto pai do item de trabalho.

  3. Chama WdfObjectDelete para excluir o objeto de trabalho ou, se o driver reativar o item de trabalho, indica que o identificador para o item de trabalho agora está disponível para reutilização.

A função de retorno de chamada de cada item de trabalho deve executar uma tarefa relativamente curta. O sistema operativo fornece um número limitado de threads de trabalho do sistema, assim o driver pode afetar o desempenho do sistema se utilizar funções de retorno de chamada de item de trabalho para executar tarefas demoradas.

Criando e excluindo itens de trabalho

Os drivers podem usar uma das duas técnicas a seguir para criar e excluir itens de trabalho:

  • Use cada item de trabalho uma vez: crie o item de trabalho quando precisar dele e exclua-o imediatamente após ser usado.

    Esta técnica é útil para condutores que requerem uma utilização pouco frequente (menos de uma vez por minuto) de um pequeno número de itens de trabalho.

    Por exemplo, a função de retorno de chamada EvtInterruptDpc de um driver pode chamar WdfWorkItemCreate e, em seguida, WdfWorkItemEnqueue, e a função de retorno de chamada EvtWorkItem do item de trabalho pode chamar WdfObjectDelete.

    Se o driver seguir esse cenário e se sua função de retorno de chamada EvtInterruptDpc receber um valor de retorno STATUS_INSUFFICIENT_RESOURCES de WdfWorkItemCreate, o driver deverá ser capaz de adiar o trabalho necessário até que os recursos do sistema (normalmente memória) fiquem disponíveis.

  • Crie um ou mais itens de trabalho que o driver reencaminha conforme necessário.

    Essa técnica é útil para drivers que usam itens de trabalho com freqüência (mais de uma vez por minuto) ou se a função de retorno de chamada EvtInterruptDpc do driver não puder lidar facilmente com um valor de retorno de STATUS_INSUFFICIENT_RESOURCES de WdfWorkItemCreate.

    O sistema não aloca um thread de trabalho para um item de trabalho até que o driver chame WdfWorkItemEnqueue. Portanto, embora os threads de trabalho do sistema sejam um recurso limitado, a criação de itens de trabalho durante a inicialização de um dispositivo consome uma pequena quantidade de memória, mas não afeta o desempenho do sistema.

    As etapas a seguir descrevem um cenário possível:

    1. A função de retorno de chamada de um driver, EvtDriverDeviceAdd, chama WdfWorkItemCreate para obter um identificador de item de trabalho.
    2. A função de retorno de chamada EvtInterruptDpc do driver cria uma lista de ações que a função de retorno de chamada EvtWorkItem deve executar e, em seguida, chama WdfWorkItemEnqueue, usando o identificador da etapa 1.
    3. A função de retorno de chamada EvtWorkItem do driver executa a lista de ações e define um sinalizador para indicar que a função de retorno de chamada foi executada.

    Posteriormente, cada vez que a função de retorno de chamada EvtInterruptDpc do driver é chamada, ela deve determinar se a função de retorno de chamada EvtWorkItem foi executada. Se a função de retorno de chamada EvtWorkItem não tiver sido executada, a função de retorno de chamada EvtInterruptDpc não chamará WdfWorkItemEnqueue, porque o item de trabalho ainda está na fila. Nesse caso, a função de retorno de chamada EvtInterruptDpc atualiza apenas a lista de ações para a função de retorno de chamada EvtWorkItem .

    Cada item de trabalho está associado a um dispositivo ou a uma fila. Quando o dispositivo associado ou a fila é removido, a estrutura exclui todos os itens de trabalho associados, portanto, se você estiver usando essa técnica, o driver não precisa chamar WdfObjectDelete.

Alguns drivers podem precisar chamar WdfWorkItemFlush para liberar seus itens de trabalho da fila de itens de trabalho. Para obter um exemplo de uso de WdfWorkItemFlush, consulte a página de referência do método.

Se o driver chamar WdfObjectDelete em um item de trabalho pendente, o resultado dependerá do estado do item de trabalho:

Estado do item de trabalho Resultado
Criado, mas não enfileirado O item de trabalho é limpo imediatamente.
Enfileirado Chamada para WdfObjectDelete aguarda até que o item de trabalho termine a execução e, em seguida, o item de trabalho é limpo
Execução Se o driver chamar WdfObjectDelete de dentro de EvtWorkItem (no mesmo thread), WdfObjectDelete retornará imediatamente. Quando o EvtWorkItem terminar, o item de trabalho será limpo. Caso contrário, WdfObjectDelete aguarda a conclusão de EvtWorkItem.