メモリ バッファーの使用

ドライバーは通常、メモリ バッファーを使用して、フレームワークやその他のドライバーとの間でデータを渡したり、ローカルに情報を格納したりします。 このトピックでは、フレームワーク メモリ オブジェクトルックアサイド リストMDL、およびローカル バッファーについて説明します。

フレームワーク メモリ オブジェクトの使用

フレームワークでは、メモリ オブジェクトを使用して、ドライバーが受け取ってフレームワークに渡すメモリ バッファーを記述します。 各フレームワーク メモリ オブジェクトは、1 つのバッファーを表します。

メモリ オブジェクトを作成するには、ドライバーは、次のいずれかのオブジェクト メソッドを呼び出します。

受信した I/O 要求のバッファーを表すメモリ オブジェクトを取得するには、ドライバーは WdfRequestRetrieveInputMemoryWdfRequestRetrieveOutputMemory を呼び出します。 I/O 要求のバッファーの取得の詳細については、「フレームワーク ベースのドライバーでのデータ バッファーへのアクセス」を参照してください

メモリ オブジェクトのバッファーのアドレスとサイズを取得するには、ドライバーは WdfMemoryGetBuffer を呼び出します。

メモリ オブジェクトのバッファーの間でデータを移動するには、ドライバーは WdfMemoryCopyFromBuffer または WdfMemoryCopyToBuffer を呼び出します。 これらのオブジェクト メソッドは、ソースと宛先のサイズをチェックし、バッファー オーバーラン エラーを防ぎます。

ドライバーが WdfMemoryCreatePreallocated を呼び出してメモリ オブジェクトを作成した場合、その後、WdfMemoryAssignBuffer を呼び出すことによって、別のバッファーをメモリ オブジェクトに割り当てることができます。

ドライバーは、I/O ターゲットに I/O 要求を送信すると、通常、フレームワーク I/O ターゲット オブジェクト メソッドに入力バッファーまたは出力バッファーを渡します。 ドライバーは、バッファーを記述する WDF_MEMORY_DESCRIPTOR 構造体を渡すか、メモリ オブジェクト ハンドルを渡すことによって、バッファーを指定します。 (I/O 要求を同期的に送信する I/O ターゲット オブジェクト メソッドでは、WDF_MEMORY_DESCRIPTOR 構造体と、I/O 要求を非同期的に送信するメソッドには、メモリ オブジェクト ハンドルが必要です)

メモリ バッファーが有効な場合の詳細については、「メモリ バッファーのライフ サイクル」を参照してください。

ルックアサイド リストを使用する

ドライバーでほぼ同じサイズのバッファーが多数必要な場合は、ルックアサイド リストからバッファーを割り当てる必要があります。 ドライバーは、WdfLookasideListCreate を呼び出してルックアサイド リストを作成します。 その後、ドライバーは WdfMemoryCreateFromLookaside を呼び出すことによって、ルックアサイド リストからバッファーを取得できます。

ドライバーが WdfMemoryCreateFromLookaside を呼び出すたびに、フレームワークはメモリ オブジェクトを作成し、ルックアサイド リストからバッファーを取得し、そのバッファーをオブジェクトに割り当てます。 ドライバーは、これらのメモリ オブジェクトのいずれかを使用して完了すると、WdfObjectDelete を呼び出します。これにより、メモリ オブジェクトが削除され、バッファー領域がルックアサイド リストに返されます。

オペレーティング システムは、ルックアサイド リストに割り当てられているメモリ リソースを管理します。 ドライバーが WdfMemoryCreateFromLookaside を初めて呼び出したときなど、使用可能でないときにルックアサイド リストからバッファーを要求した場合、システムはバッファーを割り当て、リストに割り当てます。 ドライバーが WdfObjectDelete を呼び出すと (バッファー領域がルックアサイド リストに返されます)、システムは、ドライバーが再び必要になるまで、現在割り当てられていないバッファーを一覧に保持します。 必要に応じて、リストのサイズが大きくなります。たとえば、バッファーをより頻繁に要求するドライバーは、より大きなルックアサイド リストを受け取ります。 一方、ドライバーがバッファーをすべて使用していない場合は、システムによって一覧内のバッファーの数が減る可能性があります。

MDLs の使用

一部のドライバーは、メモリ記述子リスト (MDL) を使用してバッファーを記述します。 たとえば、ダイレクト メモリ アクセス (DMA) デバイスのドライバーは、そのメソッドを呼び出す場合、WdfDmaTransactionInitialize メソッドに MDL を渡す必要があります。

MDLs を使用するドライバーは、WdfRequestRetrieveInputWdmmdlWdfRequestRetrieveOutputWdmMdl を呼び出すことによって、受信した I/O 要求のバッファーを表す MDL を取得できます。

ほとんどのフレームワーク ベースのドライバーでは、MDL は使用されません。

ローカル バッファーの割り当て

フレームワークに渡さないローカルの内部バッファー領域を必要とするドライバーは、バッファーを表すメモリ オブジェクトを作成する必要はありません。 ドライバーは、ExAllocatePoolWithTag を呼び出して内部バッファーを割り当てることができます。 ドライバーがバッファーの使用を完了したら、ExFreePoolWithTag を呼び出す必要があります。

ただし、ドライバーは、ローカル バッファーのメモリ オブジェクトを使用することもできます。 ExAllocatePoolWithTag を呼び出す代わりにメモリ バッファーを使用する利点として、各オブジェクトの親オブジェクトが削除されたときに、フレームワークによってメモリ オブジェクトとそのバッファーが自動的に削除される点を挙げることができます。

重要

このトピックで説明する ExAllocatePool DDI は、Windows 10 バージョン 2004 で非推奨となり、ExAllocatePool2ExAllocatePool3 に置き換えられました。 詳細については、「非推奨の ExAllocatePool 呼び出しを ExAllocatePool2 および ExAllocatePool3 にアップグレードする」を参照してください。

バッファーの配置

ドライバーは、WDF_ALIGN_SIZE_UP または WDF_ALIGN_SIZE_DOWN 関数を使用して、指定した配置オフセットに合わせたバッファー サイズを計算できます。 この計算は、ドライバーが複数の連続したバッファーを割り当てる必要がある場合は、各バッファーがアドレス配置境界で開始する必要がある場合に役立ちます。