Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Драйверы, которые должны динамически выделять буферы фиксированного размера для выполнения операций ввода-вывода по запросу, могут использовать подпрограммы поддержки 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 .