Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Драйверы, которые должны динамически выделять буферы фиксированного размера для выполнения операций ввода-вывода по запросу, могут использовать подпрограммы поддержки ExXxxLookasideListEx или ExXxxLookasideList. После инициализации такого драйвера операционная система будет содержать некоторое количество динамически выделенных буферов заданного размера в списке временного хранения драйвера, фактически резервируя набор повторно используемых буферов фиксированного размера для драйвера. Формат и содержимое буферов фиксированного размера драйвера (также известных как записи) в списке lookaside определяются драйвером.
Например, драйверы классов хранения, которые должны установить блоки запросов SCSI (SRBs) для базовых драйверов SCSI-портов/минипортов, используют обходные списки. Такой драйвер класса выделяет буферы для SRB по мере необходимости из своего списка lookaside и освобождает каждый буфер SRB обратно в этот список для использования повторно, когда SRB возвращается драйверу класса в завершенном IRP. Поскольку драйвер класса хранения не может заранее определить, сколько SRBs ему необходимо использовать в любое время, так как нагрузка ввода-вывода на драйвер увеличивается и снижается, список lookaside является удобным и экономным способом управления выделением и освобождением буферов для SRBs фиксированного размера в таком драйвере.
Операционная система поддерживает состояние всех страничных и непагированных списков lookaside, которые в настоящее время используются, динамически отслеживая спрос на выделение и распределение записей во всех списках и доступный системный пул для новых записей. Когда спрос на выделения ресурсов высок, операционная система увеличивает количество записей, которые она содержит в каждом списке lookaside. Когда спрос снова падает, он освобождает избыточные записи lookaside обратно в системный пул.
Списки Lookaside являются потокобезопасными. Список lookaside имеет встроенную синхронизацию для включения нескольких параллельных потоков в драйвере для совместного использования списка lookaside. Эти потоки могут безопасно выделять буферы из общего списка быстрого доступа и возвращать их в список без необходимости явной синхронизации этих операций драйвером. Однако, чтобы избежать возможных утечек и повреждения данных, набор потоков, совместно использующих список lookaside, должен явно синхронизировать инициализацию и удаление списка.
Интерфейсы списков Lookaside
Начиная с Windows Vista, структура LOOKASIDE_LIST_EX описывает список lookaside, который может содержать страницы или непагированные буферы. Если драйвер предоставляет пользовательские подпрограммы Выделить и Освободить для этого списка предварительного выделения, эти подпрограммы получают приватный контекст в качестве входного параметра. Драйвер может использовать этот контекст для сбора конфиденциальных данных для списка lookaside. Например, контекст может использоваться для подсчета количества записей списка, которые динамически выделяются и освобождаются в списке. Пример кода, демонстрирующий использование контекста таким образом, см. в разделе ExInitializeLookasideListEx.
Следующие системные подпрограммы поддерживают списки lookaside, описанные структурой LOOKASIDE_LIST_EX :
Начиная с Windows 2000 структура PAGED_LOOKASIDE_LIST описывает список lookaside, содержащий страничные буферы. Если драйвер предоставляет пользовательские подпрограммы "Выделить " и "Бесплатный " для этого списка lookaside, эти подпрограммы не получают закрытый контекст в качестве входного параметра. По этой причине, если драйвер предназначен для запуска только в Windows Vista и более поздних версиях Windows, рассмотрите возможность использования LOOKASIDE_LIST_EX структуры вместо структуры PAGED_LOOKASIDE_LIST для списков lookaside. Следующие системные подпрограммы поддерживают списки lookaside, описываемые структурой PAGED_LOOKASIDE_LIST :
ExAllocateFromPagedLookasideList
ExInitializePagedLookasideList
Начиная с Windows 2000, структура NPAGED_LOOKASIDE_LIST описывает список lookaside, содержащий непагаченные буферы. Если драйвер предоставляет пользовательские подпрограммы Выделить и Освободить для этого списка ожидания, эти подпрограммы не получают закрытый контекст в качестве входного параметра. Опять же, если драйвер предназначен для запуска только в Windows Vista и более поздних версиях Windows, рассмотрите возможность использования структуры LOOKASIDE_LIST_EX вместо структуры NPAGED_LOOKASIDE_LIST для списков lookaside. Следующие системные подпрограммы поддерживают списки lookaside, описанные структурой NPAGED_LOOKASIDE_LIST :
ExAllocateFromNPagedLookasideList
ExInitializeNPagedLookasideList
Рекомендации по реализации
Чтобы реализовать список lookaside, использующий структуру LOOKASIDE_LIST_EX , выполните следующие рекомендации по проектированию:
Вызовите ExInitializeLookasideListEx , чтобы настроить список lookaside. В этом вызове укажите, должны ли записи в списке lookaside быть страничными или нестраничными буферами. Используйте непагированные буферы, если драйвер или любой драйвер более низкого уровня, которому он передает свои записи в список lookaside, может получить доступ к этим записям на уровне IRQL >= DISPATCH_LEVEL. Используйте раздельные буферы только в том случае, если доступ к записям списка lookaside драйвера всегда выполняется на уровне IRQL <= APC_LEVEL.
Структура LOOKASIDE_LIST_EX для списка lookaside всегда должна находиться в неспециализированной системной памяти независимо от того, являются ли записи в списке постраничными или беспостраничными.
Для повышения производительности передавайте указатели NULL для параметров Allocate и Free функции ExInitializeLookasideListEx, если только подпрограммы выделения и освобождения памяти не должны выполнять больше, чем просто выделение и освобождение памяти для записей из lookaside list. Например, эти подпрограммы могут записывать сведения об использовании динамически выделенных буферов драйвера.
Предоставленная драйвером подпрограмма Allocate может передавать входные параметры (PoolType, Tag и Size), которые она получает, непосредственно в подпрограмму ExAllocatePoolWithTag или ExAllocatePoolWithQuotaTag для выделения нового буфера.
Для каждого вызова ExAllocateFromLookasideListEx сделайте обратный вызов ExFreeToLookasideListEx как можно скорее, когда ранее выделенная запись больше не используется.
Поставление подпрограмм Allocate и Free, которые не делают ничего больше, чем вызовы ExAllocatePoolWithTag и ExFreePool соответственно, приводит к потерям процессорных циклов. ExAllocateFromLookasideListEx делает необходимые вызовы ExAllocatePoolWithTag и ExFreePool автоматически, когда драйвер передает nullAllocate и Free указатели на ExInitializeLookasideListEx.
Любая подпрограмма , предоставляемая драйвером, не должна выделять память для записи из страничного пула, которая будет храниться в непагированном списке lookaside или наоборот. Он также должен выделять записи фиксированного размера, так как любой последующий вызов драйвера к ExAllocateFromLookasideListEx возвращает первую запись, которая в настоящее время хранится в списке lookaside, если список не пуст. То есть вызов ExAllocateFromLookasideListEx вызывает предоставленную драйвером подпрограмму "Allocate" только в том случае, если заданный список lookaside в настоящий момент пуст. Таким образом, при каждом вызове ExAllocateFromLookasideListEx возвращенная запись будет именно того размера, который требуется драйверу, лишь в том случае, если все записи в списке «lookaside» имеют фиксированный размер. Предоставленная драйвером подпрограмма Выделение не должна также изменять значение тега, которое драйвер первоначально передал в ExInitializeLookasideListEx, так как изменения значения тега пула усложнят отладку и отслеживание использования памяти драйвера.
Вызовы функции ExFreeToLookasideListEx помещают ранее выделенные записи в список кэша, если только этот список еще не заполнен (то есть список уже содержит максимальное количество записей, определенное системой). Для повышения производительности драйвер должен сделать обратный вызов ExFreeToLookasideListEx , как можно быстрее, как это может для каждого вызова, который он делает для ExAllocateFromLookasideListEx. Когда драйвер быстро освобождает записи обратно в список lookaside, следующий вызов этого драйвера ExAllocateFromLookasideListEx с меньшей вероятностью приведет к снижению производительности из-за динамического выделения памяти для новой записи.
Аналогичные рекомендации применяются к списку lookaside, использующему PAGED_LOOKASIDE_LIST или структуру NPAGED_LOOKASIDE_LIST .