Функция ExInitializeLookasideListEx (wdm.h)

Подпрограмма ExInitializeLookasideListEx инициализирует список lookaside.

Синтаксис

NTSTATUS ExInitializeLookasideListEx(
  [out]          PLOOKASIDE_LIST_EX    Lookaside,
  [in, optional] PALLOCATE_FUNCTION_EX Allocate,
  [in, optional] PFREE_FUNCTION_EX     Free,
  [in]           POOL_TYPE             PoolType,
  [in]           ULONG                 Flags,
  [in]           SIZE_T                Size,
  [in]           ULONG                 Tag,
  [in]           USHORT                Depth
);

Параметры

[out] Lookaside

Указатель на инициализируемую структуру LOOKASIDE_LIST_EX . При возврате эта структура описывает пустой список lookaside. Вызывающий объект должен использовать для этой структуры неоплаченное системное пространство, независимо от того, выделены ли записи в списке lookaside из страничной или невыгружаемой памяти. На 64-разрядных платформах эта структура должна быть выровнена по 16 байтам.

[in, optional] Allocate

Указатель на предоставленную вызывающей стороной подпрограмму LookasideListAllocateEx , которая выделяет новую запись списка lookaside-list. Подпрограмма ExAllocateFromLookasideListEx вызывает эту подпрограмму LookasideListAllocateEx , если список lookaside пуст (не содержит записей). Этот параметр является необязательным и может быть указан как NULL , если пользовательская подпрограмма выделения не требуется. Если этот параметр имеет значение NULL, вызовы ExAllocateFromPagedLookasideList автоматически выделяют выгружаемое или не погашенное хранилище (как определено параметром PoolType ) для новых записей.

[in, optional] Free

Указатель на предоставленную вызывающей стороной подпрограмму LookasideListFreeEx , которая освобождает ранее выделенную запись списка lookaside-list. Подпрограмма ExFreeToPagedLookasideList вызывает эту подпрограмму LookasideListFreeEx , если список просмотров заполнен (то есть список уже содержит максимальное количество записей, определенное операционной системой). Этот параметр является необязательным и может быть указан как NULL , если пользовательская процедура освобождения не требуется. Если этот параметр имеет значение NULL, вызовы ExFreeToPagedLookasideList автоматически освобождают хранилище для указанных записей.

[in] PoolType

Указывает тип пула записей в списке lookaside. Задайте для этого параметра допустимое значение перечисления POOL_TYPE .

[in] Flags

Задает необязательное значение флага для изменения поведения по умолчанию подпрограммы LookasideListAllocateEx . Задайте для этого параметра значение 0 или один из следующих битов флага EX_LOOKASIDE_LIST_EX_FLAGS_XXX .

Бит флага Описание
EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL Если выделение не удается, создайте исключение.
EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE Если выделение завершается сбоем, возвращается значение NULL , а не исключение. Этот флаг предназначен для использования с подпрограммой выделения, например ExAllocatePoolWithQuotaTag, которая взимает квоты за использование пула.

Эти два бита флагов являются взаимоисключающими.

Если параметр Allocate имеет значение NULL, установите для флагов значение ноль или EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, но не EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE. В противном случае поведение подпрограммы выделения по умолчанию не определено.

Если Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL, то значение параметра PoolType побитовое значение ORed с битом флага POOL_RAISE_IF_ALLOCATION_FAILURE для формирования значения параметра PoolType , передаваемого в подпрограмму LookasideListAllocateEx . Подпрограмма LookasideListAllocateEx может передавать это значение PoolType без изменения в подпрограмму ExAllocatePoolWithTag. Дополнительные сведения о флаге POOL_RAISE_IF_ALLOCATION_FAILURE см. в разделе ExAllocatePoolWithTag.

Если Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE, значение параметра PoolType побитовое значение ORed с битом флага POOL_QUOTA_FAIL_INSTEAD_OF_RAISE для формирования значения параметра PoolType , передаваемого в подпрограмму LookasideListAllocateEx . Подпрограмма LookasideListAllocateEx может передавать это значение PoolType без изменения в подпрограмму ExAllocatePoolWithQuotaTag. Дополнительные сведения о флаге POOL_QUOTA_FAIL_INSTEAD_OF_RAISE см. в разделе ExAllocatePoolWithQuotaTag.

[in] Size

Задает размер (в байтах) каждой записи в списке lookaside.

[in] Tag

Указывает тег пула с четырьмя байтами, используемый для пометки выделенного хранилища для записей списка lookaside. Дополнительные сведения о тегах пула см. в описании параметра Tag в ExAllocatePoolWithTag.

[in] Depth

Зарезервировано. Всегда устанавливайте для этого параметра нулевое значение.

Возвращаемое значение

ExInitializeLookasideListEx возвращает STATUS_SUCCESS, если вызов выполнен успешно. Возможные возвращаемые значения включают следующий код ошибки:

Код возврата Описание
STATUS_INVALID_PARAMETER_4 Недопустимое значение параметра PoolType .
STATUS_INVALID_PARAMETER_5 Недопустимое значение параметра Flags .

Комментарии

Драйвер должен вызвать эту подпрограмму для инициализации списка lookaside, прежде чем драйвер сможет начать использовать список. Список lookaside — это пул буферов фиксированного размера, которыми драйвер может управлять локально, чтобы уменьшить количество вызовов процедур выделения систем и, таким образом, повысить производительность. Буферы хранятся в виде записей в списке lookaside. Все записи в списке имеют одинаковый универсальный размер, который задается параметром Size .

После возврата ExInitializeLookasideListEx список lookaside инициализируется, но не содержит записей. Когда клиент вызывает подпрограмму ExAllocateFromLookasideListEx для запроса записи, эта подпрограмма определяет, что список lookaside пуст, и вызывает предоставленную драйвером подпрограмму LookasideListAllocateEx для динамического выделения хранилища для новой записи. В ответ на аналогичные запросы от клиентов могут быть выделены дополнительные записи. Позже, когда клиенты вызывают ExFreeToLookasideListEx для освобождения этих записей, эта подпрограмма вставляет записи в список lookaside. Если количество записей в списке достигает предела, определенного операционной системой, ExFreeToLookasideListEx перестает добавлять дополнительные записи в список и вместо этого передает эти записи в предоставленную драйвером подпрограмму LookasideListFreeEx для освобождения.

Если драйвер не предоставляет подпрограммы LookasideListAllocateEx и LookasideListFreeEx , процедуры ExAllocateFromLookasideListEx и ExFreeToLookasideListEx используют подпрограммы выделения и освобождения по умолчанию.

Предоставление процедур LookasideListAllocateEx и LookasideListFreeEx , которые не выполняют никаких действий, кроме вызова ExAllocatePoolWithTag и ExFreePool. Этого же эффекта можно добиться с более высокой производительностью, просто задав для параметров Allocate и Freeзначение NULL.

Перед выгрузкой драйвер должен явным образом освободить все созданные списки lookaside. Невыполнение этого действия является серьезной ошибкой программирования. Вызовите подпрограмму ExDeleteLookasideListEx , чтобы освободить список lookaside. Эта процедура освобождает хранилище для всех оставшихся записей в указанном списке lookaside, а затем удаляет список из системного набора активных списков lookaside.

Операционная система отслеживает все списки lookaside, которые используются в настоящее время. Так как объем доступной памяти без загрузки и потребность в записях списка lookaside меняются со временем, операционная система динамически корректирует свои ограничения на максимальное количество записей в каждом невыгребованном списке lookaside.

В Windows 2000 и более поздних версиях Windows список lookaside, содержащий постраничные или невыгружаемые записи, можно описать с помощью структуры PAGED_LOOKASIDE_LIST или NPAGED_LOOKASIDE_LIST соответственно.

Дополнительные сведения о списках lookaside см. в разделе Использование lookaside Списки.

Вызывающие операторы ExInitializeLookasideListEx могут выполняться в IRQL <= DISPATCH_LEVEL, но обычно выполняются в IRQL = PASSIVE_LEVEL.

Примеры

Подпрограммы LookasideListAllocateEx и LookasideListFreeEx , предоставляемые драйвером, получают параметры Lookaside , указывающие на LOOKASIDE_LIST_EX структуру, описывающую список lookaside. Подпрограммы могут использовать этот параметр для доступа к частным данным, связанным драйвером со списком lookaside. Например, драйвер может выделить экземпляр следующей структуры для сбора частных данных для каждого создаваемого списка lookaside:

typedef struct
{
  ULONG NumberOfAllocations;  // number of entries allocated
  ULONG NumberOfFrees;        // number of entries freed
  LOOKASIDE_LIST_EX LookasideField;
} MY_PRIVATE_DATA;

Драйвер может инициализировать список lookaside, как показано в следующем примере кода:

#define ENTRY_SIZE  256
#define MY_POOL_TAG  'tsLL'      
MY_PRIVATE_DATA *MyContext;
NTSTATUS status = STATUS_SUCCESS;
 
MyContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MY_PRIVATE_DATA), MY_POOL_TAG);
if (MyContext)
{
    MyContext.NumberOfAllocations = 0;
    MyContext.NumberOfFrees = 0;

    status = ExInitializeLookasideListEx(
                 &MyContext.LookasideField,
                 MyLookasideListAllocateEx,
                 MyLookasideListFreeEx,
                 NonPagedPool,
                 0,
                 ENTRY_SIZE,
                 MY_POOL_TAG,
                 0);
}
else
{
    status = STATUS_INSUFFICIENT_RESOURCES;
}

В следующем примере кода показано, как подпрограмма LookasideListAllocateEx может использовать свой параметр Lookaside для доступа к частным данным, связанным со списком lookaside:

PVOID
  MyLookasideListAllocateEx(
    __in POOL_TYPE  PoolType,
    __in SIZE_T  NumberOfBytes,
    __in ULONG  Tag,
    __inout PLOOKASIDE_LIST_EX  Lookaside)
{
    MY_PRIVATE_DATA *MyContext;
    PVOID NewEntry;

    MyContext = CONTAINING_RECORD(Lookaside, MY_PRIVATE_DATA, LookasideField);

    NewEntry = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);

    if (NewEntry)
    {
        ULONG NumberOfAllocations = (ULONG) InterlockedIncrement((LONG volatile*)&MyContext->NumberOfAllocations);
    }

    return NewEntry;
}

Макрос CONTAINING_RECORD определен в файле заголовка Ntdef.h. Подпрограмма LookAsideListFreeEx также может использовать свой параметр Lookaside для доступа к частным данным.

После того как подпрограмма MyLookasideListAllocateEx в этом примере возвращается, ExAllocateFromLookasideListEx вставляет буфер, на который указывает переменная NewEntry , в список lookaside. Чтобы сделать эту операцию вставки потокобезопасной, ExAllocateFromLookasideListEx синхронизирует доступ к списку lookaside с другими операциями вставки и удаления списков, которые могут выполняться другими потоками. Аналогичным образом, когда ExFreeFromLookasideListEx удаляет буфер из списка lookaside, он синхронизирует свой доступ к списку.

ExAllocateFromLookasideListEx и ExFreeFromLookasideListEx не синхронизируют свои вызовы с предоставленными драйвером подпрограммами LookasideListAllocateEx и LookasideListFreeEx . Таким образом, если подпрограммы MyLookasideListAllocateEx и MyLookasideListFreeEx в предыдущих примерах кода должны быть потокобезопасны, драйвер должен обеспечить необходимую синхронизацию.

Пример подпрограммы MyLookasideListAllocateEx синхронизирует доступ к переменной MyContext-NumberOfAllocations> с другими потоками, которые могут увеличивать и уменьшать эту переменную. Чтобы обеспечить такую синхронизацию, MyLookasideListAllocateEx вызывает подпрограмму InterlockedIncrement для атомарного увеличения этой переменной. Аналогичным образом, подпрограмма MyLookasideListFreeEx (не показана) может вызывать подпрограмму InterlockedDecrement для атомарного уменьшения этой переменной.

Однако если единственной целью переменной MyContext-NumberOfAllocations> в предыдущем примере кода является просто сбор статистики по выделениям списков lookaside, атомарные приращения и уменьшения вряд ли нужны. В этом случае удаленная возможность пропущенного приращения или уменьшения не должна вызывать беспокойства.

Дополнительные сведения о потокобезопасности для списков lookaside см. в разделе Использование Списки Lookaside.

Требования

Требование Значение
Минимальная версия клиента Доступно начиная с Windows Vista.
Целевая платформа Универсальное
Верхняя часть wdm.h (включая Wdm.h, Ntddk.h, Ntifs.h)
Библиотека NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <= DISPATCH_LEVEL (см. раздел "Примечания")

См. также раздел

ExAllocateFromLookasideListEx

ExAllocatePoolWithQuotaTag

ExAllocatePoolWithTag

ExDeleteLookasideListEx

ExFreePool

ExFreeToLookasideListEx

InterlockedDecrement

InterlockedIncrement

LOOKASIDE_LIST_EX

LookasideListAllocateEx

LookasideListFreeEx

NPAGED_LOOKASIDE_LIST

PAGED_LOOKASIDE_LIST

POOL_TYPE