ExInitializeLookasideListEx 関数 (wdm.h)
ExInitializeLookasideListEx ルーチンは、ルックアサイド リストを初期化します。
構文
NTSTATUS ExInitializeLookasideListEx(
[out] PLOOKASIDE_LIST_EX Lookaside,
[in, optional] PALLOCATE_FUNCTION_EX Allocate,
[in, optional] PFREE_FUNCTION_EX Free,
[in] POOL_TYPE PoolType,
[in] ULONG Flags,
[in] SIZE_T Size,
[in] ULONG Tag,
[in] USHORT Depth
);
パラメーター
[out] Lookaside
初期化する LOOKASIDE_LIST_EX 構造体へのポインター。 返された場合、この構造体は空のルックアサイド リストを記述します。 呼び出し元は、ルックアサイド・リスト内の項目がページ・メモリーまたは非ページ・メモリーから割り振られているかどうかに関係なく、この構造体に非ページ・システム・スペースを使用する必要があります。 64 ビット プラットフォームでは、この構造体は 16 バイトアラインされている必要があります。
[in, optional] Allocate
新しい lookaside-list エントリを割り当てる、呼び出し元が指定した LookasideListAllocateEx ルーチンへのポインター。 ExAllocateFromLookasideListEx ルーチンは、ルックアサイド リストが空の場合 (エントリが含まれない) 場合に、この LookasideListAllocateEx ルーチンを呼び出します。 このパラメーターは省略可能であり、カスタム割り当てルーチンが必要ない場合は NULL として指定できます。 このパラメーターが NULL の場合、 ExAllocateFromPagedLookasideList を呼び出すと、( PoolType パラメーターによって決定される) ページまたは非ページ ストレージが新しいエントリに自動的に割り当てられます。
[in, optional] Free
以前に割り当てられた lookaside-list エントリを解放する、呼び出し元から提供された LookasideListFreeEx ルーチンへのポインター。 ExFreeToPagedLookasideList ルーチンは、ルックアサイド リストがいっぱいの場合に、この LookasideListFreeEx ルーチンを呼び出します (つまり、オペレーティング システムによって決定されるエントリの最大数がリストに既に含まれています)。 このパラメーターは省略可能であり、カスタム割り当て解除ルーチンが必要ない場合は NULL として指定できます。 このパラメーターが NULL の場合、 ExFreeToPagedLookasideList を呼び出すと、指定されたエントリのストレージが自動的に解放されます。
[in] PoolType
ルックアサイド リスト内のエントリのプールの種類を指定します。 このパラメーターを有効なPOOL_TYPE列挙値 に 設定します。
[in] Flags
LookasideListAllocateEx ルーチンの既定の動作を変更する省略可能なフラグ値を指定します。 このパラメーターを 0 に設定するか、次のいずれかのEX_LOOKASIDE_LIST_EX_FLAGS_XXX フラグ ビットに 設定します。
フラグ ビット | 説明 |
---|---|
EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAIL | 割り当てが失敗した場合は、例外を発生させます。 |
EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISE | 割り当てが失敗した場合は、例外を発生させる代わりに NULL を 返します。 このフラグは、プールの使用にクォータを課金する割り当てルーチン ( ExAllocatePoolWithQuotaTag など) で使用することを目的としています。 |
これら 2 つのフラグ ビットは相互に排他的です。
Allocate が NULL の場合は、フラグを 0 またはEX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAILに設定しますが、EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISEには設定しません。 それ以外の場合、既定の割り当てルーチンの動作は未定義です。
Flags = EX_LOOKASIDE_LIST_EX_FLAGS_RAISE_ON_FAILの場合、PoolType パラメーター値は、LookasideListAllocateEx ルーチンに渡される PoolType パラメーター値を形成するために、POOL_RAISE_IF_ALLOCATION_FAILURE フラグ ビットを持つビットごとの ORed になります。 LookasideListAllocateEx ルーチンは、変更せずにこの PoolType 値を ExAllocatePoolWithTag ルーチンに渡すことができます。 POOL_RAISE_IF_ALLOCATION_FAILURE フラグの詳細については、「 ExAllocatePoolWithTag」を参照してください。
Flags = EX_LOOKASIDE_LIST_EX_FLAGS_FAIL_NO_RAISEの場合、PoolType パラメーター値はビットごとの ORed で、POOL_QUOTA_FAIL_INSTEAD_OF_RAISE フラグ ビットを使用して、LookasideListAllocateEx ルーチンに渡される PoolType パラメーター値を形成します。 LookasideListAllocateEx ルーチンは、変更せずにこの PoolType 値を ExAllocatePoolWithQuotaTag ルーチンに渡すことができます。 POOL_QUOTA_FAIL_INSTEAD_OF_RAISE フラグの詳細については、「 ExAllocatePoolWithQuotaTag」を参照してください。
[in] Size
ルックアサイド リスト内の各エントリのサイズをバイト単位で指定します。
[in] Tag
割り当てられたストレージをルックアサイド・リスト項目にマークするために使用する 4 バイト・プール・タグを指定します。 プール タグの詳細については、ExAllocatePoolWithTag の Tag パラメーターの説明を参照してください。
[in] Depth
予約済み。 常に、このパラメーターを 0 に設定します。
戻り値
呼び出しが成功した場合、ExInitializeLookasideListEx はSTATUS_SUCCESSを返します。 可能な戻り値には、次のエラー コードが含まれます。
リターン コード | 説明 |
---|---|
STATUS_INVALID_PARAMETER_4 | PoolType パラメーター値が無効です。 |
STATUS_INVALID_PARAMETER_5 | Flags パラメーターの値が無効です。 |
注釈
ドライバーは、リストの使用を開始する前に、ルックアサイド リストを初期化するには、このルーチンを呼び出す必要があります。 ルックアサイド リストは、ドライバーがローカルで管理してシステム割り当てルーチンの呼び出しの数を減らし、それによってパフォーマンスを向上させることができる固定サイズのバッファーのプールです。 バッファーは、ルックアサイド リストにエントリとして格納されます。 リスト内のすべてのエントリは、 Size パラメーターで指定された同じ均一サイズです。
ExInitializeLookasideListEx が返されると、ルックアサイド リストは初期化されますが、エントリは含まれます。 クライアントが ExAllocateFromLookasideListEx ルーチンを呼び出してエントリを要求すると、このルーチンはルックアサイド リストが空であると判断し、ドライバーが提供する LookasideListAllocateEx ルーチンを呼び出して、新しいエントリの記憶域を動的に割り当てます。 クライアントからの同様の要求に応じて、追加のエントリが割り当てられる場合があります。 その後、クライアントが ExFreeToLookasideListEx を呼び出してこれらのエントリを解放すると、このルーチンによって、そのエントリがルックアサイド リストに挿入されます。 リスト内のエントリの数がオペレーティング システムによって決定される制限に達した場合、 ExFreeToLookasideListEx はリストへのエントリの追加を停止し、代わりにこれらのエントリをドライバーが提供する LookasideListFreeEx ルーチンに渡して解放します。
ドライバーで LookasideListAllocateEx ルーチンと LookasideListFreeEx ルーチンが指定されていない場合、 ExAllocateFromLookasideListEx ルーチンと ExFreeToLookasideListEx ルーチンでは、代わりに既定の割り当てルーチンと割り当て解除ルーチンが使用されます。
ExAllocatePoolWithTag と ExFreePool を呼び出す以外に何もしない LookasideListAllocateEx ルーチンと LookasideListFreeEx ルーチンを提供してもメリットはありません。 Allocate パラメーターと Free パラメーターを NULL に設定するだけで、パフォーマンスを向上させることで、同じ効果を実現できます。
ドライバーをアンロードする前に、作成したルックアサイド リストを明示的に解放する必要があります。 これを行わないと、重大なプログラミング エラーになります。 ExDeleteLookasideListEx ルーチンを呼び出して、ルックアサイド リストを解放します。 このルーチンは、指定されたルックアサイド リスト内の残りのエントリのストレージを解放し、システム全体のアクティブなルックアサイド リストのセットからリストを削除します。
オペレーティング システムは、現在使用されているすべてのルックアサイド リストを追跡します。 使用可能な非ページ メモリの量とルックアサイド リスト エントリの需要の両方が時間の経過と共に異なるため、オペレーティング システムは、非ページルックアサイド リストのエントリの最大数に対する制限を動的に調整します。
Windows 2000 以降のバージョンの Windows では、ページまたは非ページ エントリを含むルックアサイド リストは、それぞれ PAGED_LOOKASIDE_LIST または NPAGED_LOOKASIDE_LIST 構造で記述できます。
ルックアサイド リストの詳細については、「Lookaside Listsの使用」を参照してください。
ExInitializeLookasideListEx の呼び出し元は IRQL <= DISPATCH_LEVELで実行できますが、通常は IRQL = PASSIVE_LEVELで実行されます。
例
ドライバー提供の LookasideListAllocateEx ルーチンと LookasideListFreeEx ルーチンはどちらも、ルックアサイド リストを記述するLOOKASIDE_LIST_EX構造体を指す Lookaside パラメーターを受け取ります。 ルーチンは、このパラメーターを使用して、ドライバーがルックアサイド リストに関連付けたプライベート データにアクセスできます。 たとえば、ドライバーは、作成するルックアサイド リストごとにプライベート データを収集するために、次の構造体のインスタンスを割り当てる場合があります。
typedef struct
{
ULONG NumberOfAllocations; // number of entries allocated
ULONG NumberOfFrees; // number of entries freed
LOOKASIDE_LIST_EX LookasideField;
} MY_PRIVATE_DATA;
ドライバーは、次のコード例に示すように、ルックアサイド リストを初期化できます。
#define ENTRY_SIZE 256
#define MY_POOL_TAG 'tsLL'
MY_PRIVATE_DATA *MyContext;
NTSTATUS status = STATUS_SUCCESS;
MyContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MY_PRIVATE_DATA), MY_POOL_TAG);
if (MyContext)
{
MyContext.NumberOfAllocations = 0;
MyContext.NumberOfFrees = 0;
status = ExInitializeLookasideListEx(
&MyContext.LookasideField,
MyLookasideListAllocateEx,
MyLookasideListFreeEx,
NonPagedPool,
0,
ENTRY_SIZE,
MY_POOL_TAG,
0);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
次のコード例は、 LookasideListAllocateEx ルーチンが Lookaside パラメーターを使用して、ルックアサイド リストに関連付けられているプライベート データにアクセスする方法を示しています。
PVOID
MyLookasideListAllocateEx(
__in POOL_TYPE PoolType,
__in SIZE_T NumberOfBytes,
__in ULONG Tag,
__inout PLOOKASIDE_LIST_EX Lookaside)
{
MY_PRIVATE_DATA *MyContext;
PVOID NewEntry;
MyContext = CONTAINING_RECORD(Lookaside, MY_PRIVATE_DATA, LookasideField);
NewEntry = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
if (NewEntry)
{
ULONG NumberOfAllocations = (ULONG) InterlockedIncrement((LONG volatile*)&MyContext->NumberOfAllocations);
}
return NewEntry;
}
CONTAINING_RECORD マクロは Ntdef.h ヘッダー ファイルで定義されています。 LookAsideListFreeEx ルーチンも同様に、Lookaside パラメーターを使用してプライベート データにアクセスできます。
この例の MyLookasideListAllocateEx ルーチンが戻った後、 ExAllocateFromLookasideListEx はNewEntry 変数が指すバッファーをルックアサイド リストに挿入します。 この挿入操作をスレッド セーフにするために、 ExAllocateFromLookasideListEx は 、ルックアサイド リストへのアクセスを、他のスレッドによって実行される可能性のある他のリストの挿入および削除操作と同期します。 同様に、 ExFreeFromLookasideListEx がルックアサイド リストからバッファーを削除すると、リストへのアクセスが同期されます。
ExAllocateFromLookasideListEx および ExFreeFromLookasideListEx は、ドライバーが提供する LookasideListAllocateEx ルーチンおよび LookasideListFreeEx ルーチンへの呼び出しを同期しません。 したがって、前のコード例の MyLookasideListAllocateEx ルーチンと MyLookasideListFreeEx ルーチンがスレッド セーフである必要がある場合、ドライバーは必要な同期を提供する必要があります。
このサンプル ルーチン MyLookasideListAllocateEx は、MyContext-NumberOfAllocations> 変数へのアクセスを、この変数をインクリメントおよびデクリメントする可能性のある他のスレッドと同期します。 この同期を提供するために、 MyLookasideListAllocateEx はInterlockedIncrement ルーチンを呼び出して、この変数をアトミックにインクリメントします。 同様に、 MyLookasideListFreeEx ルーチン (図示せず) は InterlockedDecrement ルーチンを呼び出して、この変数をアトミックにデクリメントできます。
ただし、前のコード例の MyContext-NumberOfAllocations> 変数の唯一の目的が、ルックアサイド リストの割り当てに関する統計を収集することだけの場合、アトミックインクリメントとデクリメントはほとんど必要になりません。 この場合、増分またはデクリメントが見逃されるリモートの可能性は問題になりません。
ルックアサイド リストのスレッド セーフの詳細については、「Lookaside Listsの使用」を参照してください。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows Vista 以降で使用できます。 |
対象プラットフォーム | ユニバーサル |
Header | wdm.h (Wdm.h、Ntddk.h、Ntifs.h を含む) |
Library | NtosKrnl.lib |
[DLL] | NtosKrnl.exe |
IRQL | <= DISPATCH_LEVEL (「解説」セクションを参照) |