Usando listas lookaside

Os drivers que devem alocar buffers de tamanho fixo dinamicamente para executar operações de E/S sob demanda podem usar as rotinas de suporte ExXxxLookasideListEx ou ExXxxLookasideList. Depois que esse driver inicializar sua lista de aparência, o sistema operacional conterá algum número de buffers alocados dinamicamente do tamanho determinado na lista de aparência do driver, reservando efetivamente um conjunto de buffers reutilizáveis de tamanho fixo para o driver. O formato e o conteúdo dos buffers de tamanho fixo de um driver (também conhecidos como entradas) em sua lista de aparências são determinados pelo driver.

Por exemplo, os drivers de classe de armazenamento que devem configurar blocos de solicitação SCSI (SRBs) para os drivers de porta/miniport SCSI subjacentes usam listas lookaside. Esse driver de classe aloca buffers para SRBs conforme necessário de sua lista lookaside e libera cada buffer SRB de volta para a lista lookaside para a lista lookaside a ser reutilizada sempre que um SRB é retornado para o driver de classe em um IRP concluído. Como um driver de classe de armazenamento não pode predeterminar quantos SRBs ele precisa usar a qualquer momento porque a demanda de E/S no driver aumenta e cai, uma lista de aspectos é uma maneira conveniente e econômica de gerenciar a alocação e a desalocação de buffers para SRBs de tamanho fixo em tal driver.

O sistema operacional mantém o estado sobre todas as listas de lookaside pa paged e não papagadas que estão sendo usadas no momento, acompanhando dinamicamente a demanda por alocações e desalocações de entradas em todas as listas e o pool de sistema disponível para novas entradas. Quando a demanda por alocações é alta, o sistema operacional aumenta o número de entradas que ele contém em cada lista de lookaside. Quando a demanda cai novamente, ela libera entradas de lookaside excedentes de volta para o pool do sistema.

As listas lookaside são thread-safe. Uma lista lookaside tem sincronização criada para habilitar vários threads em execução simultânea em um driver para compartilhar uma lista de lookaside. Esses threads podem alocar buffers com segurança da lista de aparência compartilhada e liberar esses buffers para a lista sem a necessidade de o driver sincronizar explicitamente essas operações. No entanto, para evitar possíveis vazamentos e dados de corrupção, um conjunto de threads que compartilham uma lista lookaside deve sincronizar de forma explicticamente a inicialização e a exclusão da lista.

Interfaces de lista lookaside

A partir do Windows Vista, a estrutura LOOKASIDE_LIST_EX descreve uma lista de aparências que pode conter buffers pa pagados ou não paeados. Se um driver fornece rotinas alocadas e gratuitas personalizadas para essa lista de aparências, essas rotinas recebem um contexto privado como um parâmetro de entrada. Um driver pode usar esse contexto para coletar dados privados para a lista lookaside. Por exemplo, o contexto pode ser usado para contar o número de entradas de lista que são alocadas dinamicamente e liberadas pela lista. Para ver um exemplo de código que mostra como usar um contexto dessa maneira, consulte ExInitializeLookasideListEx.

As seguintes rotinas fornecidas pelo sistema suportam listas lookaside que são descritas por uma LOOKASIDE_LIST_EX estrutura:

ExAllocateFromLookasideListEx

ExDeleteLookasideListEx

ExFlushLookasideListEx

ExFreeToLookasideListEx

ExInitializeLookasideListEx

A partir Windows 2000, a estrutura PAGED_LOOKASIDE_LIST descreve uma lista lookaside que contém buffers com páginas. Se um driver fornece rotinas alocadas e gratuitas personalizadas para essa lista de aparências, essas rotinas não recebem um contexto privado como um parâmetro de entrada. Por esse motivo, se o driver se destina a ser executado somente no Windows Vista e em versões posteriores do Windows, considere usar a estrutura LOOKASIDE_LIST_EX em vez da estrutura PAGED_LOOKASIDE_LIST para suas listas lookaside. As seguintes rotinas fornecidas pelo sistema suportam listas lookaside que são descritas por uma PAGED_LOOKASIDE_LIST estrutura:

ExAllocateFromPagedLookasideList

ExDeletePagedLookasideList

ExFreeToPagedLookasideList

ExInitializePagedLookasideList

A partir Windows 2000, a estrutura NPAGED_LOOKASIDE_LIST descreve uma lista lookaside que contém buffers não papagados. Se um driver fornece rotinas alocadas e gratuitas personalizadas para essa lista de aparências, essas rotinas não recebem um contexto privado como um parâmetro de entrada. Novamente, se o driver se destina a ser executado somente no Windows Vista e em versões posteriores do Windows, considere usar a estrutura LOOKASIDE_LIST_EX em vez da estrutura NPAGED_LOOKASIDE_LIST para suas listas de aparência. As seguintes rotinas fornecidas pelo sistema suportam listas lookaside que são descritas por uma NPAGED_LOOKASIDE_LIST estrutura:

ExAllocateFromNPagedLookasideList

ExDeleteNPagedLookasideList

ExFreeToNPagedLookasideList

ExInitializeNPagedLookasideList

Diretrizes de implementação

Para implementar uma lista lookaside que usa uma estrutura LOOKASIDE_LIST_EX , siga estas diretrizes de design:

  • Chame ExInitializeLookasideListEx para configurar uma lista lookaside. Nesta chamada, especifique se as entradas na lista lookaside deverão ser buffers pa pagados ou não. Use buffers não paxados se o driver em si ou qualquer driver subjacente para o qual ele passar suas entradas da lista de aparências poderá acessar essas entradas em IRQL >= DISPATCH_LEVEL. Use buffers paged somente se os acessos às entradas da lista de aparência do driver sempre ocorrerem em IRQL <= APC_LEVEL.

  • A LOOKASIDE_LIST_EX estrutura da lista lookaside sempre deve residir na memória do sistema não papagada, independentemente se as entradas na lista são pa pageadas ou não papagadas.

  • Para obter um melhor desempenho, passe ponteiros NULL para os parâmetros Allocate e Free para ExInitializeLookasideListEx , a menos que as rotinas de alocação e desalocação deverão fazer mais do que simplesmente alocar e liberar memória para entradas da lista lookaside. Por exemplo, essas rotinas podem registrar informações sobre o uso do driver de buffers alocados dinamicamente.

  • Uma rotina Alocar fornecida pelo driver pode passar os parâmetros de entrada (PoolType, Tag e Size) que recebe diretamente para a rotina ExAllocatePoolWithTag ou ExAllocatePoolWithQuotaTag para alocar um novo buffer.

  • Para cada chamada para ExAllocateFromLookasideListEx, faça a chamada recíproca para ExFreeToLookasideListEx assim que possível sempre que uma entrada alocada anteriormente não estiver mais sendo usada.

Fornecer rotinas Alocadas e Gratuitas que não fazem nada além de chamar ExAllocatePoolWithTag e ExFreePool, respectivamente, perde os ciclos do processador. ExAllocateFromLookasideListEx faz as chamadas necessárias para ExAllocatePoolWithTag e ExFreePool automaticamente quando um driver passa NULLAllocate e ponteiros livres para ExInitializeLookasideListEx.

Qualquer rotina Alocar fornecida pelo driver não deve alocar memória para que uma entrada do pool pa pa por página seja mantida em uma lista de lookaside não paxadas ou vice-versa. Ele também deve alocar entradas de tamanho fixo, pois qualquer chamada de driver subsequente para ExAllocateFromLookasideListEx retorna a primeira entrada atualmente mantida na lista lookaside, a menos que a lista esteja vazia. Ou seja, uma chamada para ExAllocateFromLookasideListEx causará uma chamada para a rotina Alocar fornecida pelo driver somente se a lista lookaside fornecida estiver vazia no momento. Portanto, a cada chamada para ExAllocateFromLookasideListEx, a entrada retornada será exatamente do tamanho que o driver precisa apenas se todas as entradas na lista lookaside são de um tamanho fixo. Uma rotina Alocar fornecida pelo driver também não deve alterar o valor tag que o driver passou originalmente para ExInitializeLookasideListEx, pois as alterações no valor da marca de pool dificultariam a depuração e o acompanhamento do uso de memória do driver.

Chamadas para ExFreeToLookasideListEx armazenam entradas alocadas anteriormente na lista lookaside, a menos que a lista já esteja cheia (ou seja, a lista contém o número máximo de entradas determinado pelo sistema). Para melhorar o desempenho, um driver deve fazer uma chamada recíproca para ExFreeToLookasideListEx o mais rápido possível para cada chamada que ele faz para ExAllocateFromLookasideListEx. Quando um driver libera entradas de volta para sua lista de aparência rapidamente, a próxima chamada desse driver para ExAllocateFromLookasideListEx tem muito menos probabilidade de incorrer na penalidade de desempenho de alocar memória dinamicamente para uma nova entrada.

Diretrizes semelhantes se aplicam a uma lista lookaside que usa uma estrutura PAGED_LOOKASIDE_LIST ou NPAGED_LOOKASIDE_LIST aparência.