オブジェクトのライフ サイクル
このトピックでは、オブジェクトの "ライフ サイクル" について、つまり、オブジェクトがオブジェクト マネージャーによって参照および追跡される仕組みについて説明します。 このトピックでは、オブジェクトを一時的または永続的なものにする方法についても説明します。
オブジェクト参照カウント
オブジェクト マネージャーが、オブジェクトへの参照数を管理します。 オブジェクトが作成されると、オブジェクト マネージャーはオブジェクトの参照カウントを 1 に設定します。 そのカウンターが 0 になると、そのオブジェクトは解放されます。
ドライバーは、オブジェクト マネージャーが操作するすべてのオブジェクトの正確な参照数を確実に保持しているようにする必要があります。 オブジェクトが途中で解放されると、システムがクラッシュする可能性があります。 参照カウントが誤って大きな数になっていると、オブジェクトはいつまでも解放されません。
オブジェクトは、ハンドルまたはポインターによって参照できます。 参照カウントに加え、オブジェクト マネージャはオブジェクトに対し開いているハンドルの数を保持します。 ハンドルを開く各ルーチンは、オブジェクト参照カウントとオブジェクト ハンドル数の両方を 1 ずつ増やします。 このようなルーチンの各呼び出しは、ZwClose への対応する呼び出しと一致する必要があります。 詳細については、「オブジェクト ハンドル」を参照してください。
カーネル モードでは、オブジェクトは、オブジェクトへのポインターによって参照することができます。 IoGetAttachedDeviceReference などのオブジェクトへのポインターを返すルーチンは、参照カウントを 1 ずつ増やします。 ドライバーは、ポインターの使用を終えたら、ObDereferenceObject を呼び出して、参照カウントを 1 ずつ減らす必要があります。
次のルーチンはすべて、オブジェクトの参照カウントを 1 つ増やします。
上記のルーチンのいずれかに対して行われる各呼び出しは、ObDereferenceObject への対応する呼び出しと一致する必要があります。
ObReferenceObject ルーチンと ObReferenceObjectByPointer ルーチンは、ドライバーが既知のオブジェクト ポインターの参照カウンターを 1 つ増やすことができるように提供されています。 ObReferenceObject は、単純に参照カウントを増やすだけです。 ObReferenceObjectByPointer は、参照カウントを増やす前にアクセス チェックを行います。
ObReferenceObjectByHandle ルーチンは、オブジェクト ハンドルを受け取り、基となるオブジェクトへのポインターを提供します。 これも参照カウントを 1 つ増やします。
一時オブジェクトと永続的オブジェクト
ほとんどのオブジェクトは一時的なものであり、使用されている限りは存在し、その後オブジェクト マネージャーによって解放されます。 永続的なオブジェクトも作成することができます。 オブジェクトが永続的な場合、オブジェクト マネージャー自体がオブジェクトへの参照を保持します。 したがって、その参照カウントはゼロより大きいままであり、オブジェクトが使用されなくなっても解放されることはありません。
一時オブジェクトは、ハンドル数がゼロ以外の場合にのみ、名前でアクセスすることができます。 ハンドル数がゼロに減ると、オブジェクト マネージャーの名前空間からオブジェクトの名前が削除されます。 このようなオブジェクトは、参照カウントがゼロより大きいままである限り、ポインタでアクセスすることができます。 永続的オブジェクトは、それらが存在する限り、名前でアクセスできます。
オブジェクトは、その作成時に、オブジェクトの OBJECT_ATTRIBUTES 構造で OBJ_PERMANENT 属性を指定することで、永続的にすることができます。 詳細については、「InitializeObjectAttributes」を参照してください。
永続的なオブジェクトを一時的なものにするには、ZwMakeTemporaryObject ルーチンを使用します 。 このルーチンにより、オブジェクトは使用されなくなった後に自動的に削除されます。 (オブジェクトに開いているハンドルがない場合、オブジェクトの名前はオブジェクト マネージャーの名前空間から直ちに削除されます。オブジェクト自体は、参照カウントがゼロになるまで保持されます。)