Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Os drivers de modo kernel podem usar proteção contra execução para acessar com segurança objetos na memória compartilhada do sistema que são criados e excluídos por outro driver de modo kernel.
Diz-se que um objeto está esgotado se todos os acessos em aberto do objeto forem concluídos e nenhuma nova solicitação para acessar o objeto for concedida. Por exemplo, um objeto compartilhado pode precisar ser executado para que possa ser excluído e substituído por um novo objeto.
O driver que possui o objeto partilhado pode permitir que outros drivers adquiram e libertem proteção contra desligamento no objeto. Quando a proteção contra desaceleração estiver em vigor, um driver diferente do proprietário poderá acessar o objeto sem o risco de que o proprietário exclua o objeto antes que o acesso seja concluído. Antes de iniciar o acesso, o driver de acesso solicita proteção contra desaceleração no objeto. Para um objeto de longa duração, esse pedido é quase sempre atendido. Depois que o acesso terminar, o driver de acesso libera sua proteção contra descida adquirida anteriormente no objeto.
Rotinas primárias de proteção contra degradações
Para começar a compartilhar um objeto, o driver proprietário do objeto chama a rotina ExInitializeRundownProtection para inicializar a proteção contra desaceleração no objeto. Após esta chamada, outros drivers que acessam o objeto podem adquirir e liberar a proteção de execução do objeto.
Um driver que acessa o objeto compartilhado chama a rotina ExAcquireRundownProtection para solicitar proteção contra desaceleração no objeto. Depois que o acesso for concluído, esse driver chama a rotina ExReleaseRundownProtection para liberar a proteção contra desaceleração no objeto.
Se o driver proprietário determinar que o objeto compartilhado deve ser excluído, esse driver aguardará para excluir o objeto até que todos os acessos pendentes do objeto sejam concluídos.
Em preparação para excluir o objeto compartilhado, o driver proprietário chama a rotina ExWaitForRundownProtectionRelease para aguardar a execução do objeto. Durante esta chamada, ExWaitForRundownProtectionRelease aguarda que todas as instâncias de proteção contra encerramento anteriormente concedidas no objeto sejam liberadas, mas impede que novas solicitações de proteção contra encerramento no objeto sejam concedidas. Depois que o último acesso protegido for concluído e todas as instâncias de proteção contra execução forem liberadas, ExWaitForRundownProtectionRelease retornará e o driver proprietário poderá excluir o objeto com segurança.
ExWaitForRundownProtectionRelease bloqueia a execução do thread do driver até que todos os drivers que têm proteção run-down no objeto compartilhado liberem essa proteção. Para evitar que ExWaitForRundownProtectionRelease bloqueie a execução por períodos excessivamente longos, os threads de drivers que acessam o objeto compartilhado devem evitar ser suspensos enquanto mantêm a proteção contra descida no objeto. Por esse motivo, os drivers de acesso devem chamar ExAcquireRundownProtection e ExReleaseRundownProtection dentro de uma região crítica ou protegida, ou durante a execução em IRQL = APC_LEVEL.
Utilizações para proteção contra degradações
A proteção contra degradação é útil para fornecer acesso a um objeto compartilhado que quase sempre está disponível, mas que ocasionalmente precisa ser excluído e substituído. Os drivers que acessam dados ou que chamam rotinas neste objeto não devem tentar acessar o objeto depois que ele for excluído. Caso contrário, esses acessos inválidos podem causar comportamento imprevisível, corrupção de dados ou até mesmo falha do sistema.
Por exemplo, um driver antivírus normalmente permanece carregado na memória quando o sistema operacional está em execução. Ocasionalmente, esse driver pode precisar ser descarregado e substituído por uma versão atualizada do driver. Outros drivers enviam solicitações de E/S para o driver antivírus para acessar os dados e rotinas neste driver. Antes de enviar uma solicitação de E/S, um componente do kernel, como um gerenciador de filtros do sistema de arquivos, pode adquirir proteção contra o descarregamento prematuro do driver antivírus enquanto lida com a solicitação de E/S. Após a conclusão da solicitação de E/S, a proteção contra desaceleração pode ser liberada.
A proteção contra execução não serializa acessos a um objeto compartilhado. Se dois ou mais drivers de acesso puderem manter simultaneamente a proteção contra execução em um objeto e os acessos ao objeto precisarem ser serializados, algum outro mecanismo, como um bloqueio de exclusão mútua, deverá ser usado para serializar os acessos.
A estrutura EX_RUNDOWN_REF
Uma estrutura EX_RUNDOWN_REF rastreia o status da proteção contra degradação em um objeto compartilhado. Esta estrutura é opaca para os condutores. As rotinas de proteção contra run-down fornecidas pelo sistema usam essa estrutura para contar o número de instâncias de proteção contra run-down que estão atualmente em vigor no objeto. Estas rotinas também usam esta estrutura para monitorizar se o objeto está em processo de desativação ou degradação.
Para começar a compartilhar um objeto, o driver proprietário do objeto chama ExInitializeRundownProtection para inicializar a estrutura EX_RUNDOWN_REF associada ao objeto. Após a inicialização, o driver proprietário pode disponibilizar essa estrutura para outros drivers que exigem acesso ao objeto. Os drivers de acesso passam essa estrutura como um parâmetro para as chamadas ExAcquireRundownProtection e ExReleaseRundownProtection que adquirem e liberam proteção contra desaceleração no objeto. O driver proprietário passa essa estrutura como um parâmetro para a chamada ExWaitForRundownProtectionRelease que aguarda que o objeto seja executado para que ele possa ser excluído com segurança.
Comparação com fechaduras
A proteção contra degradação é uma das várias maneiras de garantir o acesso seguro a um objeto compartilhado. Outra abordagem é usar um bloqueio de software de exclusão mútua. Se um driver requer acesso a um objeto que está atualmente bloqueado por outro driver, o primeiro driver deve esperar que o segundo driver libere o bloqueio. No entanto, adquirir e liberar bloqueios pode se tornar um gargalo de desempenho, e os bloqueios podem consumir grandes quantidades de memória. Se usados incorretamente, os bloqueios podem fazer com que os drivers que competem pelos mesmos objetos compartilhados fiquem em deadlock. Os esforços para detetar e evitar impasses normalmente exigem o desvio de recursos computacionais substanciais.
Em contraste com os bloqueios, a proteção contra degradação tem tempo de processamento relativamente leve e requisitos de memória. Uma contagem de referência simples é associada ao objeto para garantir que a exclusão do objeto seja adiada até que todos os acessos pendentes do objeto sejam concluídos. Com essa abordagem, instruções de hardware atômicas e interligadas podem ser usadas em vez de bloqueios de software de exclusão mútua para garantir acesso seguro a um objeto. As chamadas para adquirir e liberar a proteção contra degradações geralmente são rápidas. Os benefícios do uso de um mecanismo leve, como a proteção contra degradação, podem ser significativos para um objeto compartilhado que tem uma longa vida útil e é compartilhado entre muitos motoristas.
Outras rotinas de proteção contra esgotamento
Várias outras rotinas de proteção contra degradações estão disponíveis, além das que foram mencionadas anteriormente. Essas rotinas extras podem ser usadas por alguns motoristas.
A rotina ExReInitializeRundownProtection permite que uma estrutura de EX_RUNDOWN_REF usada anteriormente seja associada a um novo objeto e inicializa a proteção contra execução nesse objeto.
A rotina ExRundownCompleted atualiza a estrutura EX_RUNDOWN_REF para indicar que o rundown do objeto associado foi concluído.
As rotinas ExAcquireRundownProtectionEx e ExReleaseRundownProtectionEx são semelhantes a ExAcquireRundownProtection e ExReleaseRundownProtection. Essas quatro rotinas aumentam ou diminuem a contagem das instâncias de proteção contra degradação que estão em vigor em um objeto compartilhado. Enquanto ExAcquireRundownProtection e ExReleaseRundownProtection incrementam e diminuem essa contagem em um, ExAcquireRundownProtectionEx e ExReleaseRundownProtectionEx incrementam e diminuem a contagem por quantias arbitrárias.
Proteção contra esgotamento com reconhecimento de cache
Uma referência de resumo é uma estrutura de dados compacta e rápida, mas pode causar contenção de cache quando muitos processadores tentam adquirir a referência ao mesmo tempo. Isso pode afetar o desempenho e a escalabilidade do seu driver.
Para evitar esse problema, você pode usar uma referência de resumo com reconhecimento de cache para distribuir o rastreamento de referência em várias linhas de cache. Isso reduz a contenção de cache e melhora o desempenho do driver em computadores com vários processadores.
Para usar uma referência de rundown com reconhecimento de cache, siga estas etapas:
- Crie um objeto EX_RUNDOWN_REF_CACHE_AWARE seguindo um destes procedimentos:
- Chame ExAllocateCacheAwareRundownProtection. Isso cuida da inicialização.
- Como alternativa, para controlar a alocação de memória, chame ExSizeOfRundownProtectionCacheAware, aloque um buffer do tamanho retornado e, em seguida, passe esse buffer e tamanho para ExInitializeRundownProtectionCacheAware.
- Solicite a proteção de rundown no objeto antes de acessá-lo, chamando a rotina ExAcquireRundownProtectionCacheAware. Essa rotina retorna TRUE se a solicitação for concedida, ou FALSE se o objeto estiver a ser desativado.
- Libere a proteção contra rundown no objeto depois de acessá-lo chamando a rotina ExReleaseRundownProtectionCacheAware .
- Aguarde até que o objeto seja executado antes de excluí-lo chamando a rotina ExWaitForRundownProtectionReleaseCacheAware . Esta rotina bloqueia o thread atual até que todas as instâncias de proteção de rundown no objeto sejam liberadas.
- Se o driver chamado ExAllocateCacheAwareRundownProtection anteriormente, ele deve chamar ExFreeCacheAwareRundownProtection para liberar a referência de rundown.
Para reutilizar uma referência de rundown com reconhecimento de cache, siga estas etapas:
- Depois de chamar ExWaitForRundownProtectionReleaseCacheAware, chame ExRundownCompletedCacheAware para indicar que o rundown do objeto antigo foi concluído.
- Chame ExReInitializeRundownProtectionCacheAware para reinicializar a referência depois de o objeto associado ser desligado ou encerrado.
- Agora o driver pode chamar novamente ExAcquireRundownProtectionCacheAware.
Uma referência de rundown com reconhecimento de cache tem a vantagem de melhor desempenho e escalabilidade em situações específicas, mas consome mais memória do que uma referência de rundown regular. Você deve considerar esse trade-off ao escolher entre os dois tipos de referências de rundown.