Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Um driver que requer processamento atrasado pode usar um work item, que contém um ponteiro para uma rotina de retorno de chamada que realiza o processamento. O driver enfileira o item de trabalho e um thread de trabalho do sistema remove o item de trabalho da fila e executa a rotina de retorno de chamada do driver. O sistema mantém um pool desses threads de trabalho do sistema, que são responsáveis por processar cada um deles um item de trabalho por vez.
O driver associa uma rotina de retorno de chamada WorkItem ao item de trabalho. Quando o thread de trabalho do sistema processa o item de trabalho, ele chama a rotina WorkItem associada. No Windows Vista e versões posteriores do Windows, um driver pode associar uma rotina WorkItemEx a um item de trabalho. WorkItemEx usa parâmetros diferentes dos parâmetros que o WorkItem usa.
As rotinas WorkItem e WorkItemEx são executadas em um contexto de thread do sistema. Se uma rotina de despacho de driver puder ser executada em um contexto de thread no modo de usuário, essa rotina poderá chamar uma rotina WorkItem ou WorkItemEx para realizar quaisquer operações que exijam um contexto de thread do sistema.
Para usar um item de trabalho, um driver executa as seguintes etapas:
Aloque e inicialize um novo item de trabalho.
O sistema usa uma estrutura IO_WORKITEM para manter um item de trabalho. Para alocar uma nova estrutura de IO_WORKITEM e inicializá-la como um item de trabalho, o driver pode chamar IoAllocateWorkItem. No Windows Vista e versões posteriores do Windows, o driver pode, como alternativa, alocar sua própria estrutura de IO_WORKITEM e chamar IoInitializeWorkItem para inicializar a estrutura como um item de trabalho. (O driver deve chamar IoSizeofWorkItem para determinar o número de bytes necessários para manter um item de trabalho.)
Associe uma rotina de retorno de chamada ao item de trabalho e enfileira o item de trabalho para que ele seja processado por um thread de trabalho do sistema.
Para associar uma rotina WorkItem ao item de trabalho e enfileirar o item de trabalho, o driver deve chamar IoQueueWorkItem. Para associar uma rotina WorkItemEx ao item de trabalho e enfileirar o item de trabalho, o driver deve chamar IoQueueWorkItemEx.
Depois que o item de trabalho não for mais necessário, libere-o.
Um item de trabalho que foi alocado por IoAllocateWorkItem deve ser liberado pelo IoFreeWorkItem. Um item de trabalho que foi inicializado por IoInitializeWorkItem deve ser não inicializado pelo IoUninitializeWorkItem antes de ser liberado.
O item de trabalho só pode ser desinicializado ou liberado quando não está atualmente na fila. O sistema desativa o item de trabalho antes de chamar a rotina de retorno de chamada do item de trabalho, de modo que IoFreeWorkItem e IoUninitializeWorkItem podem ser chamados de dentro do retorno de chamada.
Um DPC que precisa iniciar uma tarefa de processamento que requer processamento longo ou que faça uma chamada de bloqueio deve delegar o processamento dessa tarefa a um ou mais itens de trabalho. Enquanto um DPC é executado, todos os threads são impedidos de serem executados. Além disso, um DPC, que é executado em IRQL = DISPATCH_LEVEL, não deve fazer chamadas de bloqueio. No entanto, o thread de trabalho do sistema que processa um item de trabalho é executado em IRQL = PASSIVE_LEVEL. Assim, o item de trabalho pode conter chamadas bloqueantes. Por exemplo, um thread de trabalho do sistema pode esperar em um objeto dispatcher.
Como o pool de threads de trabalho do sistema é um recurso limitado, as rotinas WorkItem e WorkItemEx só podem ser usadas para operações que levam um curto período de tempo. Se uma dessas rotinas for executada por muito tempo (se contiver um loop indefinido, por exemplo) ou aguardar muito tempo, o sistema poderá ficar em deadlock. Portanto, se um driver exigir longos períodos de processamento atrasado, ele deverá, em vez disso, chamar PsCreateSystemThread para criar seu próprio thread do sistema.
Não chame IoQueueWorkItem ou IoQueueWorkItemEx para enfileirar um item de trabalho que já esteja na fila. Isso pode causar corrupção de estruturas de dados do sistema. Se o driver enfileirar o mesmo item de trabalho sempre que uma rotina de driver específica for executada, você poderá usar a seguinte técnica para evitar enfileirar o item de trabalho uma segunda vez se ele já estiver na fila:
- O driver mantém uma lista de tarefas para a rotina de trabalho.
- Essa lista de tarefas está disponível no contexto fornecido para a rotina de trabalho. A rotina de trabalho e as rotinas de driver que modificam a lista de tarefas sincronizam seu acesso à lista.
- Sempre que a rotina de trabalho é executada, ela executa todas as tarefas na lista e remove cada tarefa da lista à medida que a tarefa é concluída.
- Quando uma nova tarefa chega, o driver adiciona essa tarefa à lista. O driver enfileira o item de trabalho somente se a lista de tarefas estiver vazia anteriormente.
O thread de trabalho do sistema remove o item de trabalho da fila antes de chamar o thread de trabalho. Assim, um thread do driver pode enfileirar com segurança o item de trabalho novamente assim que a worker thread iniciar sua execução.