MmLockPagableCodeSection マクロ (wdm.h)
MmLockPagableCodeSection ルーチンは、特別なコンパイラ ディレクティブでマークされたドライバー ルーチンのセットを含むドライバー コードのセクションをシステム空間にロックします。
構文
void MmLockPagableCodeSection(
[in] Address
);
パラメーター
[in] Address
シンボリック アドレスを指定します。 このアドレスは、通常、 #pragma alloc_text (PAGExxxx、driverfunction) などのマークが付けられたドライバー コードのセクション内のドライバー関数の名前です。 その後、 PAGExxxx セクションのすべての関数は、この関数が返されるときにロックダウンされます。
戻り値
なし
解説
MmLockPagableCodeSection は、オペレーティング システムがドライバー コードのこのセクションを識別するために使用する不透明な値を返します。 この不透明な値は、後で MmLockPagableSectionByHandle (ドライバーがロックを解除してからセクションを再ロックする場合) または MmUnlockPagableImageSection に渡すことができます。
MmLockPagableCodeSection ルーチンと MmUnlockPagableImageSection (反対のアクションを実行するルーチン) は、次の操作を実行できるドライバーをサポートします。
ドライバーのデバイスに対する受信 I/O 要求によって、これらのルーチンが IRP を処理する必要が生じるまで、ドライバー ルーチンのサブセットを常駐メモリに読み込むのを延期します。
I/O 要求の処理が完了し、ドライバーのデバイスに対する追加の要求が現在想定されていない場合は、同じドライバー ルーチンのサブセットをページングで使用できるようにします。
MmLockPagableCodeSection、 MmLockPagableSectionByHandle 、 MmUnlockPagableImageSection は、次の特性を持つデバイスおよび中間ドライバーで使用することを目的としています。
ドライバーには、システムの実行中に不要なコード パスがありますが、必要な場合は、任意のスレッド コンテキストまたは IRQL >= DISPATCH_LEVELで実行されるため、ドライバーのコードは常駐である必要があります。
ドライバーは、ページング可能なルーチンを読み込むタイミングと、再びページングできるタイミングを正確に判断できます。
たとえば、システム提供のフォールト トレラント ディスク ドライバーでは、ミラー セット、ストライプ セット、ボリューム セットの作成がサポートされています。 ただし、特定のマシンは、ミラー セット、ストライプ セット、ボリューム セット、またはこれら 3 つの可能なオプションの任意の組み合わせでのみ構成できます。 このような状況では、システム ftdisk ドライバーは、ミラー、ストライプ、ボリューム セットをページング可能なコード セクションに属するものとして明示的にサポートするルーチンをマークすることで、読み込まれたイメージのサイズを小さくします。 ドライバーの初期化中、ページング可能なコード セクションは、ユーザーがディスクにミラー、ストライプ、またはボリューム セットを設定した場合にのみ常駐になります。 ユーザーがディスクを動的に再パーティション分割すると、ftdisk ドライバーは、ユーザーが要求するミラー、ストライプ、またはボリューム セットをサポートするために必要なページング可能なコード セクションをロックダウンします。
他の例として、システム提供のシリアル ドライバーと並列ドライバーには DispatchCreate ルーチンと DispatchClose ルーチンがあり、特定のポートが排他的 I/O 用に開かれた場合と、開いているポートのハンドルが解放されたときに呼び出されます。 ただし、シリアル I/O 要求と並列 I/O 要求は散発的であり、エンド ユーザーが現在実行しているアプリケーションと、エンド ユーザーが現在実行しているアプリケーション オプションによって決まります。 このような状況では、システムのシリアル ドライバーと並列ドライバーは、I/O 用に最初のポートが開かれたときにのみ DispatchCreate ルーチンが常駐するページング可能なコード セクションに属する多くのルーチンをマークすることで、読み込まれたイメージのサイズを小さくします。
前述の各システム ドライバーは、ページング可能なセクションを持つという両方の条件を満たすことに注意してください。ドライバーには、システムの実行中に不要なコード パスがあり、ドライバーはページング可能なセクションを読み込むタイミングを正確に判断でき、再びページングできます。
セクションをロックダウンするのはコストのかかる操作であるため、ドライバーがページング可能なコード セクションを複数の場所でロックダウンする場合は、最初の要求に MmLockPagableCodeSection を使用します。 MmLockPagableCodeSection によって返されるハンドルを渡して MmLockPagableSectionByHandle を呼び出して、後続のロック要求を行います。 メモリ マネージャーは、読み込まれたモジュール リストを検索するのではなく、不透明な戻り値を使用して関連するセクションをすばやく検索するため、ハンドルによるロックにより、ドライバーのパフォーマンスが大幅に向上します。 ロックされたセクションは、 MmUnlockPagableImageSection を呼び出すことによってロック解除されます。
ページング可能なコード セクション内の各ドライバー ルーチンは、次のコンパイラ ディレクティブでマークする必要があります。
#pragma alloc_text(PAGExxxx, DriverRoutine)
ここで xxxx は、呼び出し元のページング可能セクションの 4 文字の一意識別子 (省略可能) で、DriverRoutine はページング可能なコード セクションに含めるエントリ ポイントです。 キーワード (keyword) PAGE とドライバーによって決定されるサフィックス (最大 4 文字) は大文字と小文字が区別されます。つまり、PAGE は大文字にする必要があります。
たとえば、ドライバーの DispatchCreate ルーチンなどの MmLockPagableCodeSection を 1 回呼び出すと、同じ PAGExxxx 識別子でマークされたすべてのドライバー ルーチンを含むセクション全体がシステム空間でロックされます。
特定の種類のドライバー ルーチンは、次のようなドライバーのページング可能セクションの一部にすることはできません。
ISR をページング可能にしないでください。 特に割り込みベクトルを共有できる場合、デバイス ドライバーは、デバイスが使用されていない場合でも、誤った割り込みを受け取る可能性があります。 一般に、ドライバーがデバイスで割り込みを明示的に無効にできる場合でも、ISR をページング可能にしないでください。
ISR からキューに入れられる可能性のある DpcForIsr ルーチンや CustomDpc ルーチンなど、DPC がキューに入れられるタイミングをドライバーが制御できない場合は、DPC ルーチンをページング可能にしないでください。 一般に、IRQL >= DISPATCH_LEVELで実行され、任意のスレッド コンテキストで呼び出したり、ランダムな外部イベントに応答して呼び出したりできるドライバー ルーチンをページング可能にすることはできません。
システム ページング I/O パスの一部である可能性があるドライバーで DispatchRead ルーチンまたは DispatchWrite ルーチンをページング可能にしないでください。 システム ページ ファイルを含む可能性があるディスクのドライバーには、システムの実行中に常駐する DispatchRead ルーチンと DispatchWrite ルーチンが必要です。このようなディスク ドライバーの上に階層化されているすべてのドライバーが必要です。
コンパイラ ディレクティブ #pragma alloc_text(PAGExxxx, ...) でマークされたページング可能なセクション内のルーチンは、コンパイラ ディレクティブ #pragma alloc_text(INIT, ...) でマークされたルーチンとは異なります。 INIT セクションのルーチンはページング可能ではなく、 ドライバーが DriverEntry または 再初期化 ルーチン (存在する場合) から戻るとすぐに破棄されます。
メモリ マネージャーは、ドライバーのページング可能なセクションに対して内部ロック数を保持します。 MmLockPagableCodeSection を呼び出してこのカウントをインクリメントすると、逆数の MmUnlockPagableImageSection によってカウントがデクリメントされます。 ドライバーのページング可能なセクションは、この数が 0 でない限り、ページングできません。
ページング可能なコード セクションの作成の詳細については、「ドライバーを ページング可能にする」を参照してください。
要件
要件 | 値 |
---|---|
対象プラットフォーム | デスクトップ |
Header | wdm.h (Wdm.h、Ntddk.h、Ntifs.h を含む) |
Library | NtosKrnl.lib |
[DLL] | NtosKrnl.exe |
IRQL | <=APC_LEVEL |