Partilhar via


Usando Bloqueios de Framework

Às vezes, os drivers devem fornecer uma sincronização específica para o driver em funções de retorno de chamada relacionadas a pedidos de E/S, seja como complemento ou substituição à sincronização fornecida pelo framework. Os drivers podem usar bloqueios de sincronização de retorno de chamada, bloqueios de rotação, bloqueios de espera e bloqueios de interrupção para sincronizar o código do driver.

Bloqueios de sincronização de retorno de chamada

Se tiver configurado o seu driver para usar a funcionalidade de sincronização automática da estrutura, a estrutura adquire um bloqueio de sincronização antes de chamar as funções de retorno de chamada relacionadas aos eventos de solicitação de E/S do driver.

Esses bloqueios de sincronização de callback, que estão associados a objetos de dispositivos do framework e objetos de fila, também podem ser adquiridos por drivers. Para adquirir um bloqueio de sincronização, um driver chama WdfObjectAcquireLock. Para liberar o bloqueio, o driver chama WdfObjectReleaseLock.

Talvez queira que o seu driver use os bloqueios de sincronização de retorno de chamada se ele usar a sincronização ao nível do dispositivo ou ao nível da fila da estrutura para funções de retorno de chamada relacionadas a pedidos de E/S, mas necessitar sincronizar algum código executado em IRQL = PASSIVE_LEVEL com funções de retorno de chamada que operam em IRQL = DISPATCH_LEVEL. Isso ocorre porque os drivers podem usar a sincronização automática somente para funções de retorno de chamada que são executadas no mesmo IRQL.

Por exemplo, um driver pode usar a sincronização automática para um objeto de item de trabalho somente se o nível de execução do objeto pai do item de trabalho for WdfExecutionLevelPassive (porque a função de retorno de chamada de um item de trabalho é sempre executada em IRQL= PASSIVE_LEVEL). Portanto, se um driver especificar como WdfExecutionLevelDispatch no membro ExecutionLevel da estrutura WDF_OBJECT_ATTRIBUTES de um objeto de dispositivo, o driver não poderá definir o membro AutomaticSerialization da estrutura de configuração de um objeto de item de trabalho filho. Em vez disso, o driver deve adquirir um bloqueio de sincronização de retorno de chamada para sincronizar as funções de retorno de chamada EvtWorkItem com as funções de retorno de chamada do objeto de dispositivo pai.

Bloqueios de espera do Framework

Utilize bloqueios de espera do framework para sincronizar o acesso aos dados do driver a partir do código que é executado em IRQL = PASSIVE_LEVEL. Antes que um driver possa usar um bloqueio de espera de estrutura, ele deve chamar WdfWaitLockCreate para criar um objeto de bloqueio de espera. O driver pode então chamar WdfWaitLockAcquire para adquirir o bloqueio e WdfWaitLockRelease liberá-lo.

Framework Bloqueios de Rotação

Use bloqueios de rotação da estrutura para sincronizar o acesso aos dados do driver a partir do código executado em IRQL <= DISPATCH_LEVEL. Quando um thread de driver adquire um bloqueio de rotação, o sistema define o IRQL do thread como DISPATCH_LEVEL. Quando o thread libera o bloqueio, o sistema restaura o IRQL do thread ao seu nível anterior.

Um driver que não utiliza a sincronização automática da estrutura pode usar um spin lock para sincronizar o acesso ao espaço de contexto de um objeto de dispositivo, se o espaço de contexto for gravável e se mais de uma das funções de retorno de chamada de evento do driver aceder a esse espaço.

Antes que um driver possa usar um bloqueio de rotação de estrutura, ele deve chamar WdfSpinLockCreate para criar um objeto spin-lock. O driver pode então chamar WdfSpinLockAcquire para adquirir o bloqueio e WdfSpinLockRelease para libertá-lo.

Para obter um exemplo do uso de fechaduras rotativas, consulte Sincronização do cancelamento de pedidos enviados.

Bloqueios de interrupção do Framework

Para objetos de interrupção que suportam manipulação de interrupção DIRQL, os bloqueios de interrupção da framework são bloqueios de rotação. Após o driver adquirir um spin lock de interrupção, ele executa no DIRQL do dispositivo até liberar o bloqueio. Para obter mais informações sobre como usar bloqueios de interrupção, consulte Sincronizando código de interrupção.

Para objetos de interrupção que suportam o manuseamento a nível passivo, os bloqueios de interrupção do framework são bloqueios de espera. Depois de o driver adquirir um bloqueio de espera de interrupção, o driver executa em IRQL = PASSIVE_LEVEL até liberar o bloqueio. Para obter mais informações sobre manipulação de nível passivo, consulte Suporte a interrupções de nível passivo.