MmGetSystemAddressForMdlSafe 関数 (wdm.h)
MmGetSystemAddressForMdlSafe は、指定した MDL で記述するバッファーの非ページ システム領域の仮想アドレスを返すマクロです。
構文
PVOID MmGetSystemAddressForMdlSafe(
[in] PMDL Mdl,
[in] ULONG Priority
);
パラメーター
[in] Mdl
対応するベース仮想アドレスをマップする対象のバッファーへのポインター。
[in] Priority
使用可能な PTE が少ない状況での成功の重要度を示す MM_PAGE_PRIORITY 値を指定します。 LowPagePriority、NormalPagePriority、HighPagePriority のいずれかの優先度の値を指定します。 Windows 8 以降では、指定した優先度の値と MdlMappingNoWrite または MdlMappingNoExecute フラグとの、ビットごとの OR 演算を行うことができます。
LowPagePriority は、システムのリソースがかなり少ない場合にマッピング要求が失敗する可能性があることを示します。 このような状況の例としては、ドライバーでマッピング エラーを処理できる、重要でないネットワーク接続が挙げられます。
NormalPagePriority は、システムのリソースが非常に少ない場合にマッピング要求が失敗する可能性があることを示します。 このような状況の例としては、重要でないローカル ファイル システム要求が挙げられます。
HighPagePriority は、システムのリソースが完全に不足していない限り、マッピング要求が失敗してはならないことを示します。 このような状況の例として、ドライバー内のページング ファイル パスが挙げられます。
MdlMappingNoWrite は、マップされた物理ページが書き込み不可 (読み取り専用) メモリとして構成されることを示します。 Windows 8以降、このフラグ ビットは、書き込みを無効にするメモリを指定するために、MM_PAGE_PRIORITY値を使用してビットごとの ORed にすることができます。
MdlMappingNoExecute は、マップされた物理ページを実行不可メモリとして構成することを示します。 Windows 8 以降では、このフラグ ビットと MM_PAGE_PRIORITY 値とのビットごとの OR 演算によって、命令の実行を無効にするメモリを指定できます。 ベスト プラクティスとして、Windows 8 以降のバージョンの Windows 用に記述されたドライバーでは、実行可能メモリが明示的に必要な場合を除き、常に実行不可メモリを指定する必要があります。
戻り値
MmGetSystemAddressForMdlSafe は、指定した MDL で記述する物理ページをマップする基本システム領域の仮想アドレスを返すマクロです。 ページがまだシステム アドレス空間にマップされておらず、ページをマップしようとして失敗した場合は、NULL が返されます。
注釈
指定した MDL によって記述した物理ページがシステム アドレス空間にまだマップされていない場合、それらのページがこのルーチンによってシステム アドレス空間にマップされます。
プログラミング I/O (PIO) デバイスのドライバーは、このルーチンを呼び出して、Irp-MdlAddress> の MDL によって記述され、ユーザー モードの仮想アドレス範囲に既にマップされているユーザー モード バッファーをシステム アドレス空間の範囲にマップします。
このルーチンに入る時点で、指定した MDL にはロックダウンされた物理ページが記述されている必要があります。 ロックダウンされた MDL は、MmProbeAndLockPages、MmBuildMdlForNonPagedPool、IoBuildPartialMdl、MmAllocatePagesForMdlEx のいずれかのルーチンを使用して作成できます。
MmGetSystemAddressForMdlSafe によって返されたシステム アドレス空間マッピングが不要になった場合、マッピングを解放する必要があります。 マッピングを解放するために必要な手順は、MDL が作成された方法によって異なります。 次の 4 つのケースが考えられます。
MDL が MmProbeAndLockPages ルーチンの呼び出しによって作成された場合、システム アドレス空間マッピングを明示的に解放する必要はありません。 代わりに、MmUnlockPages ルーチンによってマッピング (割り当てられている場合) が解放されます。
MDL が MmBuildMdlForNonPagedPool ルーチンの呼び出しによって作成された場合、MmGetSystemAddressForMdlSafe で既存のシステム アドレス空間マッピングが再利用され、新しいシステム アドレス空間マッピングは作成されません。 この場合、クリーンアップは必要ありません (つまり、ロックを解除したり、マップを解除したりする必要はありません)。
MDL が IoBuildPartialMdl ルーチンの呼び出しによって作成された場合、ドライバーによって MmPrepareMdlForReuse ルーチンまたは IoFreeMdl ルーチンが呼び出だれ、システム アドレス空間マッピングが解放される必要があります。
MDL が MmAllocatePagesForMdlEx ルーチンの呼び出しによって作成された場合、ドライバーで MmUnmapLockedPages ルーチンを呼び出して、システム アドレス空間マッピングを解放する必要があります。 MmGetSystemAddressForMdlSafe が 1 つの MDL に対して複数回呼び出された場合、後続の MmGetSystemAddressForMdlSafe 呼び出しでは、単に最初の呼び出しで作成されたマッピングだけが返されます。 このマッピングを解放するには、MmUnmapLockedPages を 1 回呼び出すだけで十分です。
Windows 7 以降および Windows Server 2008 R2 以降では、MmAllocatePagesForMdlEx によって作成された MDL に対して MmUnmapLockedPages を明示的に呼び出す必要はありません。 代わりに、MmFreePagesFromMdl ルーチンを呼び出すと、システム アドレス空間マッピング (割り当てられている場合) が解放されます。
新しいシステム アドレス空間マッピングを作成するために、MmGetSystemAddressForMdlSafe では、CacheType パラメーターを MmCached に設定して、MmMapLockedPagesSpecifyCache が呼び出されます。 MmCached 以外のキャッシュの種類を必要とするドライバーでは、MmGetSystemAddressForMdlSafe を呼び出すのではなく、MmMapLockedPagesSpecifyCache を直接呼び出す必要があります。 CacheType パラメーターの詳細については、MmMapLockedPagesSpecifyCacheに関するページを参照してください。
MmMapLockedPagesSpecifyCache の呼び出しでは、指定したキャッシュの種類は、MDL によって記述したページにキャッシュの種類がまだ関連付けられていない場合に限って使用されます。 ただし、ほぼすべての場合において、ページには既に関連付けられたキャッシュの種類があり、このキャッシュの種類が新しいマッピングに使用されます。 このルールの例外は、ページが MmAllocatePagesForMdl によって割り当てられた場合です。この場合、ページの元のキャッシュの種類に関係なく、キャッシュの種類が MmCached に設定されます。
一度に 1 つのスレッドだけが、特定の MDL に対して MmGetSystemAddressForMdlSafe を安全に呼び出すことができます。このルーチンは、呼び出し元のスレッドが MDL を所有していると想定しているためです。 ただし、同じスレッドからすべての呼び出しを行うか、呼び出しを明示的に同期する (複数のスレッドからの呼び出しの場合) ことによって、同じ MDL に対して MmGetSystemAddressForMdlSafe を複数回呼び出すことができます。
ドライバーで要求を小さい要求に分割する必要がある場合、ドライバーで追加の MDL を割り当てることができます。または、ドライバーで IoBuildPartialMdl ルーチンを使用できます。
返されるベース アドレスのオフセットは、MDL 内の仮想アドレスのオフセットと同じです。
Windows 98 で MmGetSystemAddressForMdlSafe はサポートされていません。 代わりに MmGetSystemAddressForMdl を使用してください。
このマクロでは MmMapLockedPagesSpecifyCache を呼び出すので、このマクロを使用するには、NtosKrnl.lib へのリンクが必要になることがあります。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows 2000 |
Header | wdm.h |
IRQL | <= DISPATCH_LEVEL |
DDI コンプライアンス規則 | MdlAfterReqCompletedIntIoctlA(kmdf)、 MdlAfterReqCompletedIoctlA(kmdf)、 MdlAfterReqCompletedReadA(kmdf)、 MdlAfterReqCompletedWriteA(kmdf) |