Macro MmLockPagableCodeSection (wdm.h)
A rotina MmLockPagableCodeSection bloqueia uma seção do código do driver, contendo um conjunto de rotinas de driver marcadas com uma diretiva de compilador especial, no espaço do sistema.
Sintaxe
void MmLockPagableCodeSection(
[in] Address
);
Parâmetros
[in] Address
Especifica um endereço simbólico. Esse endereço normalmente é o nome de uma função de driver em uma seção do código do driver que foi marcada com algo como #pragma alloc_text (PAGExxxx, driverfunction). Todas as funções na seção PAGExxxxx terão a garantia de serem bloqueadas quando essa função retornar.
Retornar valor
Nenhum
Comentários
MmLockPagableCodeSection retorna um valor opaco que o sistema operacional usa para identificar esta seção do código do driver. Esse valor opaco pode ser passado posteriormente para MmLockPagableSectionByHandle (se o driver desbloquear e, posteriormente, recadear a seção) ou para MmUnlockPagableImageSection.
A rotina MmLockPagableCodeSection e MmUnlockPagableImageSection (a rotina que executa a ação oposta) dão suporte a drivers que podem fazer o seguinte:
Adiar o carregamento de um subconjunto de rotinas de driver na memória residente até que as solicitações de E/S de entrada para os dispositivos do driver tornem necessário que essas rotinas processem IRPs.
Disponibilize o mesmo subconjunto de rotinas de driver para paginação quando tiver concluído o processamento de solicitações de E/S e nenhuma solicitação adicional para os dispositivos do driver é esperada no momento.
MmLockPagableCodeSection, MmLockPagableSectionByHandle e MmUnlockPagableImageSection destinam-se ao uso por drivers intermediários e de dispositivo que têm as seguintes características:
O driver tem caminhos de código que podem não ser necessários enquanto o sistema está em execução, mas, se forem necessários, o código do driver deve ser residente porque ele é executado em um contexto de thread arbitrário ou em IRQL >= DISPATCH_LEVEL.
O driver pode determinar exatamente quando as rotinas pagináveis devem ser carregadas e quando elas podem ser paginadas novamente.
Por exemplo, o driver de disco tolerante a falhas fornecido pelo sistema dá suporte à criação de conjuntos de espelho, conjuntos de distribuição e conjuntos de volumes. No entanto, um computador específico só pode ser configurado com um conjunto de espelho, apenas com um conjunto de distribuição, apenas com um conjunto de volumes ou com qualquer combinação dessas três opções possíveis. Nessas circunstâncias, o driver ftdisk do sistema reduz o tamanho de sua imagem carregada marcando rotinas que dão suporte explicitamente a conjuntos de espelho, distribuição e volume como pertencentes a seções de código pagináveis. Durante a inicialização do driver, as seções de código pagináveis só serão residentes se o usuário tiver configurado os discos para ter conjuntos de espelho, distribuição ou volume. Se o usuário reparticionar os discos dinamicamente, o driver ftdisk bloqueará quaisquer seções de código pagináveis adicionais necessárias para dar suporte a qualquer conjunto de espelho, distribuição ou volume solicitado pelo usuário.
Como outros exemplos, os drivers serial e paralelo fornecidos pelo sistema têm rotinas DispatchCreate e DispatchClose que são chamadas quando uma porta específica é aberta para E/S exclusiva e quando o identificador de uma porta aberta é liberado, respectivamente. No entanto, as solicitações de E/S em série e paralelas são esporádicas, determinadas por quais aplicativos o usuário final está executando no momento e quais opções de aplicativo o usuário final está se exercitando no momento. Nessas circunstâncias, os drivers serial e paralelo do sistema reduzem os tamanhos de suas imagens carregadas marcando muitas rotinas como pertencentes a uma seção de código paginável que a rotina DispatchCreate faz residente somente quando a primeira porta é aberta para E/S.
Observe que cada um dos drivers de sistema anteriores atende aos dois critérios para ter seções pagináveis: o driver tem caminhos de código que podem não ser necessários enquanto o sistema está em execução e o driver pode determinar exatamente quando sua seção paginável deve ser carregada e pode ser paginada novamente.
Como é uma operação cara para bloquear uma seção, se um driver bloquear uma seção de código paginável em mais de um lugar, use MmLockPagableCodeSection para a primeira solicitação. Faça solicitações de bloqueio subsequentes chamando MmLockPagableSectionByHandle passando o identificador retornado por MmLockPagableCodeSection. O bloqueio por identificador melhora significativamente o desempenho do driver porque o gerenciador de memória usa o valor retornado opaco para localizar rapidamente a seção relevante em vez de pesquisar uma lista de módulos carregados. Uma seção bloqueada é desbloqueada chamando MmUnlockPagableImageSection.
Cada rotina de driver em uma seção de código paginável deve ser marcada com a seguinte diretiva do compilador:
#pragma alloc_text(PAGExxxx, DriverRoutine)
em que xxxx é um identificador exclusivo opcional de quatro caracteres para a seção paginável do chamador e DriverRoutine é um ponto de entrada a ser incluído na seção de código paginável. O palavra-chave PAGE e o sufixo determinado pelo driver, que pode ter até quatro caracteres, diferenciam maiúsculas de minúsculas; ou seja, PAGE deve ser maiúscula.
Uma única chamada para MmLockPagableCodeSection em, por exemplo, a rotina DispatchCreate de um driver, faz com que toda a seção, contendo cada rotina de driver marcada com o mesmo identificador PAGExxxx , seja bloqueada no espaço do sistema.
Determinados tipos de rotinas de driver não podem fazer parte da seção paginável de qualquer driver, incluindo o seguinte:
Nunca torne um ISR paginável. É possível que um driver de dispositivo receba uma interrupção espúria mesmo que seu dispositivo não esteja em uso, especialmente se o vetor de interrupção puder ser compartilhado. Em geral, mesmo que um driver possa desabilitar explicitamente as interrupções em seu dispositivo, um ISR não deve ser tornado paginável.
Nunca torne uma rotina DPC paginável se o driver não puder controlar quando o DPC estiver na fila, como qualquer rotina DpcForIsr ou CustomDpc que possa ser enfileirada de um ISR. Em geral, as rotinas de driver executadas em IRQL >= DISPATCH_LEVEL e que podem ser chamadas em um contexto de thread arbitrário ou em resposta a um evento externo aleatório não devem ser tornadas pagináveis.
Nunca torne a rotina DispatchRead ou DispatchWrite paginável em qualquer driver que possa fazer parte do caminho de E/S de paginação do sistema. O driver de um disco que pode conter o arquivo de página do sistema deve ter rotinas DispatchRead e DispatchWrite residentes enquanto o sistema está em execução, assim como todos os drivers em camadas acima desse driver de disco.
Observe que as rotinas em uma seção paginável marcada com a diretiva do compilador #pragma alloc_text(PAGExxxx, ...) diferem das rotinas marcadas com a diretiva do compilador #pragma alloc_text(INIT, ...). As rotinas na seção INIT não são pagináveis e são descartadas assim que o driver retorna de seu DriverEntry ou sua rotina de reinicialização , se tiver uma.
O gerenciador de memória mantém uma contagem de bloqueio interno na seção paginável de qualquer driver. Chamadas para MmLockPagableCodeSection incrementam essa contagem e o MmUnlockPagableImageSection recíproco diminui a contagem. A seção paginável de um driver não está disponível para ser paginada, a menos que essa contagem seja zero.
Para obter mais informações sobre como criar seções de código paginável, consulte Tornando os drivers pagináveis.
Requisitos
Requisito | Valor |
---|---|
Plataforma de Destino | Área de Trabalho |
Cabeçalho | wdm.h (include Wdm.h, Ntddk.h, Ntifs.h) |
Biblioteca | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | <=APC_LEVEL |