Макрос MmLockPagableCodeSection (wdm.h)

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

Синтаксис

void MmLockPagableCodeSection(
  [in]  Address
);

Параметры

[in] Address

Задает символьный адрес. Этот адрес обычно представляет собой имя функции драйвера в разделе кода драйвера, помеченном чем-то вроде #pragma alloc_text (PAGExxxx, driverfunction). Все функции в разделе PAGExxxx будут гарантированно заблокированы при возврате этой функции.

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

None

Remarks

MmLockPagableCodeSection возвращает непрозрачное значение, которое операционная система использует для идентификации этого раздела кода драйвера. Это непрозрачное значение можно впоследствии передать в MmLockPagableSectionByHandle (если драйвер разблокирует, а затем повторно заблокирует раздел) или в MmUnlockPagableImageSection.

Подпрограмма MmLockPagableCodeSection и MmUnlockPagableImageSection (подпрограмма, выполняющая противоположное действие) поддерживают драйверы, которые могут выполнять следующие действия:

  • Отложите загрузку подмножества подпрограмм драйвера в резидентную память до тех пор, пока входящие запросы ввода-вывода для устройств драйвера не сделают их необходимыми для обработки IRP.

  • Сделайте одно и то же подмножество подпрограмм драйверов доступными для разбиения по страницам, когда они завершили обработку запросов ввода-вывода, и в настоящее время дополнительные запросы для устройств драйвера не ожидаются.

MmLockPagableCodeSection, MmLockPagableSectionByHandle и MmUnlockPagableImageSection предназначены для использования драйверами устройств и промежуточными устройствами со следующими характеристиками:

  • Драйвер имеет пути к коду, которые могут не потребоваться во время работы системы, но, если они необходимы, код драйвера должен быть резидентным, так как он выполняется в произвольном контексте потока или в IRQL >= DISPATCH_LEVEL.

  • Драйвер может точно определить, когда следует загружать подпрограммы, доступные для страницы, и когда их можно будет снова выгружать.

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

Как и в других примерах, системные последовательные и параллельные драйверы имеют подпрограммы DispatchCreate и DispatchClose , которые вызываются при открытии определенного порта для монопольного ввода-вывода и при освобождении дескриптора открытого порта соответственно. Тем не менее, последовательные и параллельные запросы ввода-вывода являются спорадическими, которые определяются тем, какие приложения выполняются конечным пользователем в данный момент и какие параметры приложения в данный момент используются конечным пользователем. В таких случаях системные последовательные и параллельные драйверы уменьшают размеры загруженных образов, помечая многие подпрограммы как относящиеся к разделу страничного кода, который подпрограмма DispatchCreate делает резидентной только при открытии первого порта для ввода-вывода.

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

Так как блокировка раздела является дорогостоящей операцией, если драйвер блокирует раздел страничного кода в нескольких местах, используйте MmLockPagableCodeSection для первого запроса. Выполните последующие запросы блокировки, вызвав MmLockPagableSectionByHandle , передав дескриптор, возвращенный MmLockPagableCodeSection. Блокировка с помощью дескриптора значительно повышает производительность драйвера, так как диспетчер памяти использует непрозрачное возвращаемое значение для быстрого поиска соответствующего раздела, а не поиска в списке загруженных модулей. Заблокированный раздел разблокируется путем вызова MmUnlockPagableImageSection.

Каждая подпрограмма драйвера в разделе страничного кода должна быть помечена следующей директивой компилятора:

#pragma alloc_text(PAGExxxx, DriverRoutine)

где xxxx — необязательный уникальный идентификатор из четырех символов для страничного раздела вызывающего объекта, а DriverRoutine — это точка входа, включаемая в раздел страничного кода. В ключевое слово PAGE и суффиксе, определяемом драйвером, который может содержать до четырех символов, регистр учитывается, то есть page должен быть прописным.

При одном вызове MmLockPagableCodeSection , например в подпрограмме DispatchCreate драйвера, весь раздел, содержащий все подпрограммы драйвера, помеченные одним и тем же идентификатором PAGExxxx , блокируется в системном пространстве.

Некоторые типы подпрограмм драйвера нельзя включить в раздел драйвера, доступный для страницы, включая следующие:

  • Никогда не делайте isr страничной. Драйвер устройства может получить фиктивное прерывание, даже если его устройство не используется, особенно если вектор прерывания можно совместно использовать. Как правило, даже если драйвер может явно отключить прерывания на своем устройстве, ISR не следует делать страничной.

  • Никогда не делайте подпрограмму DPC страничной, если драйвер не может управлять постановкой DPC в очередь, например любой подпрограммой DpcForIsr или CustomDpc , которая может быть помещена в очередь из ISR. Как правило, подпрограммы драйвера, выполняемые в IRQL >= DISPATCH_LEVEL и которые могут вызываться в произвольном контексте потока или в ответ на случайное внешнее событие, не должны быть доступны для страниц.

  • Никогда не делайте подпрограмму DispatchRead или DispatchWrite выстраиваемой в любом драйвере, который может быть частью пути системного ввода-вывода подкачки. Драйвер диска, который может содержать файл системной страницы, должен иметь подпрограммы DispatchRead и DispatchWrite , которые находятся в режиме работы системы, а также все драйверы, размещенные над таким драйвером диска.

Обратите внимание, что подпрограммы в разделе с возможностью страницы, помеченном директивой компилятора #pragma alloc_text(PAGExxxx, ...) отличаются от подпрограмм, помеченных директивой компилятора #pragma alloc_text(INIT, ...). Подпрограммы в разделе INIT недоступны для страниц и удаляются, как только драйвер возвращается из driverEntry или повторной инициализации , если она имеется.

Диспетчер памяти поддерживает внутреннее количество блокировок для любого раздела драйвера, доступного для страниц. Вызовы MmLockPagableCodeSection увеличивают это число, а обратное значение MmUnlockPagableImageSection уменьшает его. Раздел драйвера, доступный для страницы, недоступен для выгрузки, если это число не равно нулю.

Дополнительные сведения о создании разделов кода, доступных для страничных страниц, см. в статье Создание драйверов для страничных страниц.

Требования

Требование Значение
Целевая платформа Персональный компьютер
Верхняя часть wdm.h (включая Wdm.h, Ntddk.h, Ntifs.h)
Библиотека NtosKrnl.lib
DLL NtosKrnl.exe
IRQL <=APC_LEVEL

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

MmLockPagableDataSection

MmLockPagableSectionByHandle

MmPageEntireDriver

MmResetDriverPaging

MmUnlockPagableImageSection