Работа с ассоциативными списками
Иногда выделение памяти при помощи системных вызовов, описанных выше, становится неоптимальным. Например, частое выделение и освобождение мелких блоков при помощи системных вызовов оказывается причиной существенного падения быстродействия. Между тем, если известно заранее, что манипуляция будет производиться блоками определенного и постоянного размера, то имеет смысл организовать "локальную кучу", которая управлялась бы более производительными функциями.
Такую возможность предоставляет механизм ассоциативных списков (lookaside list), который реализован в системных вызовах, представленных ниже. Поначалу, ассоциативный список — это всего лишь заранее созданный заголовок, который должен хранить информацию о состоянии списка, и не содержит никаких выделенных блоков памяти. По мере выполнения вызовов ExAllocateFrom(N)PagedLookasideList
(таблицы 7.9 и 7.10) такие блоки создаются — либо системным вызовом ExAllocatePoolWithTag, либо внутри предоставленной драйвером функции (указанной драйвером параметром pAllocFunction). По мере создания и, возможно, последующего освобождения выделенных ранее блоков (системным вызовом ExFreePool, либо предоставленной драйвером функцией), ассоциативный список может оказаться держателем некоторого количества блоков фиксированного размера в страничной либо нестраничной памяти (в зависимости от способа инициализации).
Таблица 7.9. Прототип вызова ExInitializePagedLookasideList
PVOID ExInitializePagedLookasideList | IRQL < DISPATCH_LEVEL |
Параметры | Создание ассоциативного списка блоков страничной памяти |
IN PPAGED_LOOKASIDE_LIST pLookasideListHeader | Указатель на предварительно выделенную драйвером область размером sizeof(PAGED_LOOKASIDE_LIST) |
Остальные параметры совпадают с параметрами вызова ExInitializeNPagedLookasideList, см. ниже таблицу 7.10 | |
Возвращаемое значение | void |
В настоящий момент, Windows XP и Server 2003 самостоятельно и динамически определяет максимальное число элементов в ассоциативном списке.