Condividi tramite


Uso degli elenchi Lookaside

I driver che devono allocare buffer a dimensione fissa in modo dinamico per eseguire operazioni di I/O su richiesta possono usare le routine di supporto exXxxLookasideListEx o ExXxxLookasideList . Dopo che un driver di questo tipo inizializza il proprio elenco lookaside, il sistema operativo conterrà un certo numero di buffer allocati dinamicamente delle dimensioni specificate nell'elenco lookaside del driver, riservando in modo efficace un set di buffer a dimensione fissa riutilizzabili per il driver. Il formato e il contenuto dei buffer a dimensione fissa di un driver (noti anche come voci) nell'elenco lookaside sono determinati dal driver.

Ad esempio, i driver di classe di archiviazione che devono configurare blocchi di richieste SCSI (SRB) per i driver porta/miniport SCSI sottostanti usano elenchi lookaside. Un driver di classe di questo tipo alloca i buffer per i database SRB in base alle esigenze dal relativo elenco lookaside e rilascia nuovamente ogni buffer SRB nell'elenco lookaside per l'elenco lookaside da riutilizzare ogni volta che viene restituito un SRB al driver di classe in un IRP completato. Poiché un driver di classe di archiviazione non può predeterminare il numero di SRB che deve usare in qualsiasi momento perché la richiesta di I/O sul driver aumenta e cade, un elenco lookaside è un modo pratico ed economico per gestire l'allocazione e la deallocazione dei buffer per i SRB di dimensioni fisse in un driver di questo tipo.

Il sistema operativo mantiene lo stato di tutti gli elenchi lookaside di paging e non di paging attualmente utilizzati, monitorando dinamicamente la domanda di allocazioni e deallocazione delle voci in tutti gli elenchi e il pool di sistema disponibile per le nuove voci. Quando la domanda di allocazioni è elevata, il sistema operativo aumenta il numero di voci contenute in ogni elenco lookaside. Quando la domanda scende di nuovo, libera le voci lookaside in eccedenza nel pool di sistema.

Gli elenchi lookaside sono thread-safe. Un elenco lookaside include la sincronizzazione predefinita per abilitare più thread in esecuzione simultanea in un driver per condividere un elenco lookaside. Questi thread possono allocare in modo sicuro buffer dall'elenco lookaside condiviso e liberare questi buffer all'elenco senza richiedere al driver di sincronizzare in modo esplicito queste operazioni. Tuttavia, per evitare possibili perdite e danneggiamenti dei dati, un set di thread che condividono un elenco lookaside deve sincronizzare in modo esplicito l'inizializzazione e l'eliminazione dell'elenco.

Interfacce dell'elenco lookaside

A partire da Windows Vista, la struttura LOOKASIDE_LIST_EX descrive un elenco lookaside che può contenere buffer di paging o non di paging. Se un driver fornisce routine Allocate e Free personalizzate per questo elenco lookaside, queste routine ricevono un contesto privato come parametro di input. Un driver può usare questo contesto per raccogliere dati privati per l'elenco lookaside. Ad esempio, il contesto può essere usato per contare il numero di voci di elenco allocate in modo dinamico e liberate dall'elenco. Per un esempio di codice che illustra come usare un contesto in questo modo, vedere ExInitializeLookasideListEx.

Le routine fornite dal sistema seguenti supportano elenchi lookaside descritti da una struttura LOOKASIDE_LIST_EX :

ExAllocateFromLookasideListEx

ExDeleteLookasideListEx

ExFlushLookasideListEx

ExFreeToLookasideListEx

ExInitializeLookasideListEx

A partire da Windows 2000, la struttura PAGED_LOOKASIDE_LIST descrive un elenco lookaside contenente buffer di paging. Se un driver fornisce routine Allocate e Free personalizzate per questo elenco lookaside, queste routine non ricevono un contesto privato come parametro di input. Per questo motivo, se il driver è destinato all'esecuzione solo in Windows Vista e versioni successive di Windows, è consigliabile usare la struttura LOOKASIDE_LIST_EX anziché la struttura PAGED_LOOKASIDE_LIST per gli elenchi lookaside. Le routine fornite dal sistema seguenti supportano elenchi lookaside descritti da una struttura PAGED_LOOKASIDE_LIST :

ExAllocateFromPagedLookasideList

ExDeletePagedLookasideList

ExFreeToPagedLookasideList

ExInitializePagedLookasideList

A partire da Windows 2000, la struttura NPAGED_LOOKASIDE_LIST descrive un elenco lookaside che contiene buffer non di paging. Se un driver fornisce routine Allocate e Free personalizzate per questo elenco lookaside, queste routine non ricevono un contesto privato come parametro di input. Anche in questo caso, se il driver è destinato a essere eseguito solo in Windows Vista e versioni successive di Windows, è consigliabile usare la struttura LOOKASIDE_LIST_EX anziché la struttura NPAGED_LOOKASIDE_LIST per gli elenchi lookaside. Le routine fornite dal sistema seguenti supportano elenchi lookaside descritti da una struttura NPAGED_LOOKASIDE_LIST :

ExAllocateFromNPagedLookasideList

ExDeleteNPagedLookasideList

ExFreeToNPagedLookasideList

ExInitializeNPagedLookasideList

Linee guida per l'implementazione

Per implementare un elenco lookaside che usa una struttura LOOKASIDE_LIST_EX , seguire queste linee guida di progettazione:

  • Chiama ExInitializeLookasideListEx per configurare un elenco lookaside. In questa chiamata specificare se le voci nell'elenco lookaside devono essere inserite in buffer di paging o non di paging. Usare buffer non di paging se il driver stesso o qualsiasi driver sottostante a cui passa le voci dell'elenco lookaside potrebbe accedere a queste voci in IRQL >= DISPATCH_LEVEL. Usare buffer di paging solo se gli accessi alle voci dell'elenco lookaside del driver si verificano sempre in IRQL <= APC_LEVEL.

  • La struttura LOOKASIDE_LIST_EX per l'elenco lookaside deve sempre risiedere nella memoria di sistema non di paging indipendentemente dal fatto che le voci nell'elenco siano di paging o non di pagina.

  • Per prestazioni migliori, passare puntatori NULL per i parametri Allocate e Free a ExInitializeLookasideListEx , a meno che le routine di allocazione e deallocazione non debbano eseguire più di allocare e liberare memoria per le voci dell'elenco lookaside. Ad esempio, queste routine potrebbero registrare informazioni sull'utilizzo del driver di buffer allocati in modo dinamico.

  • Una routine Allocate fornita dal driver può passare i parametri di input (PoolType, Tag e Size) ricevuti direttamente alla routine ExAllocatePoolWithTag o ExAllocatePoolWithQuotaTag per allocare un nuovo buffer.

  • Per ogni chiamata a ExAllocateFromLookasideListEx, effettuare la chiamata reciproca a ExFreeToLookasideListEx appena possibile quando non viene più utilizzata una voce allocata in precedenza.

Specificare routine Allocate e Free che non fanno altro che chiamare exAllocatePoolWithTag e ExFreePool, rispettivamente, spreca i cicli del processore. ExAllocateFromLookasideListEx effettua automaticamente le chiamate necessarie a ExAllocatePoolWithTag e ExFreePool quando un driver passa puntatori NULL Allocate e Free a ExInitializeLookasideListEx.

Qualsiasi routine Allocate fornita dal driver non deve allocare memoria per una voce del pool di paging da mantenere in un elenco lookaside non di pagina o viceversa. Deve anche allocare voci a dimensione fissa, perché qualsiasi chiamata del driver successiva a ExAllocateFromLookasideListEx restituisce la prima voce attualmente contenuta nell'elenco lookaside, a meno che l'elenco non sia vuoto. Ovvero, una chiamata a ExAllocateFromLookasideListEx provoca una chiamata alla routine Allocate fornita dal driver solo se l'elenco lookaside specificato è attualmente vuoto. Pertanto, a ogni chiamata a ExAllocateFromLookasideListEx, la voce restituita sarà esattamente la dimensione necessaria per il driver solo se tutte le voci nell'elenco lookaside sono di dimensioni fisse. Una routine Allocate fornita dal driver non deve anche modificare il valore tag passato originariamente al driver exInitializeLookasideListEx, perché le modifiche apportate al valore del tag del pool renderebbero più difficile il debug e il rilevamento dell'utilizzo della memoria del driver.

Chiamate a ExFreeToLookasideListEx archivia voci allocate in precedenza nell'elenco lookaside a meno che l'elenco non sia già pieno (ovvero l'elenco contiene il numero massimo di voci determinato dal sistema). Per prestazioni migliori, un driver deve effettuare una chiamata reciproca a ExFreeToLookasideListEx il più rapidamente possibile per ogni chiamata eseguita a ExAllocateFromLookasideListEx. Quando un driver libera rapidamente le voci al suo lookaside list, la successiva chiamata del driver a ExAllocateFromLookasideListEx è molto meno probabile che si verifichi una riduzione delle prestazioni dell'allocazione dinamica della memoria per una nuova voce.

Linee guida simili si applicano a un elenco lookaside che usa una struttura PAGED_LOOKASIDE_LIST o NPAGED_LOOKASIDE_LIST .