Alocando memória System-Space

Importante

Os DDIs exAllocatePool discutidos neste tópico foram preteridos em Windows 10, versão 2004 e foram substituídos por ExAllocatePool2 e ExAllocatePool3. Para obter mais informações, consulte Atualizando chamadas de ExAllocatePool preteridas para ExAllocatePool2 e ExAllocatePool3.

Os drivers podem usar o espaço alocado pelo sistema em suas extensões de dispositivo como áreas de armazenamento global para obter informações específicas do dispositivo. Os drivers podem usar apenas a pilha de kernel para passar pequenas quantidades de dados para suas rotinas internas. Alguns drivers precisam alocar quantidades adicionais e maiores de memória de espaço do sistema, normalmente para buffers de E/S.

Para alocar espaço de buffer de E/S, as melhores rotinas de alocação de memória a serem usadas são MmAllocateNonCachedMemory, MmAllocateContiguousMemorySpecifyCache, AllocateCommonBuffer (se o dispositivo do driver usar o DMA master barramento ou o modo de inicialização automática de um controlador de DMA do sistema) ou ExAllocatePoolWithTag.

O pool nãopagado normalmente se torna fragmentado à medida que o sistema é executado, portanto, a rotina driverEntry de um driver deve chamar essas rotinas para configurar quaisquer buffers de E/S de longo prazo necessários pelo driver. Cada uma dessas rotinas, exceto ExAllocatePoolWithTag, aloca memória alinhada em um limite específico do processador (determinado pelo tamanho da linha de cache de dados do processador) para fornecer o melhor desempenho.

Os drivers devem alocar buffers de E/S da forma mais econômica possível, pois a memória do pool nãopagado é um recurso limitado do sistema. Normalmente, um driver deve evitar chamar essas rotinas de suporte repetidamente para solicitar alocações de menos de PAGE_SIZE porque cada alocação menor que PAGE_SIZE também vem com um cabeçalho de pool usado para gerenciar internamente a alocação.

Dicas para alocar espaço de buffer do driver economicamente

Para alocar a memória do buffer de E/S economicamente, lembre-se do seguinte:

  • Cada chamada para MmAllocateNonCachedMemory ou MmAllocateContiguousMemorySpecifyCache sempre retorna um múltiplo completo do tamanho da página do sistema, de memória de espaço do sistema nãopagada, qualquer que seja o tamanho da alocação solicitada. Portanto, as solicitações para menos de uma página são arredondadas para uma página inteira e todos os bytes restantes na página são desperdiçados; eles são inacessíveis pelo driver que chamou a função e são inutilizáveis por outro código do modo kernel.

  • Cada chamada para AllocateCommonBuffer usa pelo menos um registro de mapa de objetos do adaptador, que mapeia pelo menos um byte e, no máximo, uma página. Para obter mais informações sobre registros de mapa e uso de buffers comuns, consulte Objetos do Adaptador e DMA.

Alocando memória com ExAllocatePoolWithTag

Os drivers também podem chamar ExAllocatePoolWithTag, especificando um dos seguintes valores de POOL_TYPE definidos pelo sistema para o parâmetro PoolType :

  • PoolType = NonPagedPool para quaisquer objetos ou recursos não armazenados em uma extensão de dispositivo ou extensão de controlador que o driver possa acessar enquanto estiver em execução no IRQL > APC_LEVEL.

    Para esse valor PoolType , ExAllocatePoolWithTag alocará a quantidade de memória solicitada se o NumberOfBytes especificado for menor ou igual a PAGE_SIZE. Caso contrário, todos os bytes restantes na última página alocada serão desperdiçados: inacessíveis para o chamador e inutilizáveis por outro código do modo kernel.

    Por exemplo, em um x86, uma solicitação de alocação de 5 quilobytes (KB) retorna duas páginas de 4 KB. Os últimos 3 KB da segunda página não estão disponíveis para o chamador ou outro chamador. Para evitar o perda de pool nãopagado, o driver deve alocar várias páginas com eficiência. Nesse caso, por exemplo, o driver pode fazer duas alocações, uma para PAGE_SIZE e outra para 1 KB, para alocar um total de 5 KB.

    Nota A partir do Windows Vista, o sistema adiciona automaticamente a memória adicional para que duas alocações sejam desnecessárias.

  • PoolType = PagedPool para memória que sempre é acessada em IRQL <= APC_LEVEL e não está no caminho de gravação do sistema de arquivos.

ExAllocatePoolWithTag retornará um ponteiro NULL se não puder alocar o número solicitado de bytes. Os drivers devem sempre marcar o ponteiro retornado. Se seu valor for NULL, a rotina DriverEntry (ou qualquer outra rotina de driver que retorne valores NTSTATUS) deverá retornar STATUS_INSUFFICIENT_RESOURCES ou manipular a condição de erro, se possível.