次の方法で共有


高速ミューテックスと保護されたミューテックス

Windows 2000 以降では、ドライバーは、IRQL <= APC_LEVELで実行されるコードに対してオーバーヘッドの少ない相互除外が必要な場合に、高速ミューテックスを使用できます。 高速ミューテックスは、一度に 1 つのスレッドのみが入力する必要があるコード パスを保護できます。 保護されたコード パスを入力するために、スレッドはミューテックスを 取得します 。 別のスレッドが既にミューテックスを取得している場合、ミューテックスが解放されるまで、現在のスレッドの実行は中断されます。 保護されたコード パスを終了するために、スレッドはミューテックスを 解放 します。

Windows Server 2003 以降では、ドライバーは 保護されたミューテックスを使用することもできます。 保護されたミューテックスは高速ミューテックスのドロップイン置換ですが、パフォーマンスが向上します。 高速ミューテックスと同様に、保護されたミューテックスは、一度に 1 つのスレッドのみが入力する必要があるコード パスを保護できます。 ただし、保護されたミューテックスを使用するコードは、高速ミューテックスを使用するコードよりも高速に実行されます。

Windows 8 より前のバージョンの Windows では、ガードミューテックスは高速ミューテックスとは異なる方法で実装されています。 高速ミューテックスによって保護されるコード パスは、IRQL = APC_LEVELで実行されます。 保護されたミューテックスによって保護されているコード パスは、IRQL <= APC_LEVELで実行されますが、すべての APC が無効になっています。 これらの以前のバージョンの Windows では、保護されたミューテックスの取得は、高速ミューテックスの取得よりも高速な操作です。 ただし、これら 2 種類のミューテックスは同じように動作し、同じ制限の対象となります。 特に、IRQL = APC_LEVELで呼び出すことのできないカーネル ルーチンは、高速ミューテックスまたは保護されたミューテックスによって保護されているコード パスから呼び出さないでください。

Windows 8 以降では、保護されたミューテックスは高速ミューテックスとして実装されます。 保護されたミューテックスまたは高速ミューテックスによって保護されているコード パスでは、 ドライバー検証ツール は、IRQL = APC_LEVELで発生するカーネル ルーチンへの呼び出しを扱います。 以前のバージョンの Windows と同様に、APC_LEVEL での不正な呼び出しは、保護されたミューテックスまたは高速ミューテックスで保護されたコード パスでも許可されません。

高速ミューテックス

高速ミューテックスは、 FAST_MUTEX 構造体によって表されます。 ドライバーは、 FAST_MUTEX 構造体に独自の記憶域を割り当て、その構造体を初期化する ExInitializeFastMutex ルーチンを呼び出します。

スレッドは、次のいずれかの方法で高速ミューテックスを取得します。

  • ExAcquireFastMutex ルーチンの呼び出し。 ミューテックスが既に別のスレッドによって取得されている場合、ミューテックスが使用可能になるまで、呼び出し元のスレッドの実行は中断されます。

  • ExTryToAcquireFastMutex ルーチンを呼び出して、現在のスレッドを中断せずに高速ミューテックスを取得しようとします。 ミューテックスが取得されたかどうかに関係なく、ルーチンは直ちに戻ります。 ExTryToAcquireFastMutex は、呼び出し元のミューテックスを正常に取得した場合に TRUE を返します。それ以外の場合は FALSE を返します。

スレッドは ExReleaseFastMutex を呼び出して、 ExAcquireFastMutex または ExTryToAcquireFastMutex によって取得された高速ミューテックスを解放します。

高速ミューテックスによって保護されるコード パスは、IRQL = APC_LEVELで実行されます。 ExAcquireFastMutexExTryToAcquireFastMutex は現在の IRQL をAPC_LEVELに上げ、 ExReleaseFastMutex は元の IRQL を復元します。 したがって、スレッドが高速ミューテックスを保持している間は、すべての APC が無効になります。

コード パスが常に APC_LEVEL で実行されていることが保証されている場合、ドライバーは代わりに ExAcquireFastMutexUnsafeExReleaseFastMutexUnsafe を呼び出して、高速ミューテックスを取得して解放できます。 これらのルーチンは現在の IRQL を変更せず、現在の IRQL がAPC_LEVELされている場合にのみ安全に使用できます。

高速ミューテックスは再帰的に取得できません。 既に高速ミューテックスを保持しているスレッドが取得しようとすると、そのスレッドはデッドロックします。 高速ミューテックスは、IRQL <= APC_LEVEL で実行されるコードでのみ使用できます。

保護されたミューテックス

保護されたミューテックス (Windows Server 2003 以降) は、高速ミューテックスと同じ機能を実行しますが、パフォーマンスは向上します。

Windows 8 以降では、保護されたミューテックスと高速ミューテックスが同じように実装されます。

Windows 8 より前のバージョンの Windows では、保護されたミューテックスは高速ミューテックスとは異なる方法で実装されています。 高速ミューテックスを取得すると、現在のIRQLがAPC_LEVELに引き上げられます。一方、保護されたミューテックスを取得すると、ガード領域に入りますが、こちらの操作の方が高速です。 保護されたリージョンの詳細については、「重要なリージョンと保護されたリージョンの」を参照してください。

保護されたミューテックスは、 KGUARDED_MUTEX 構造体によって表されます。 ドライバーは、 KGUARDED_MUTEX 構造体に独自の記憶域を割り当てるし、構造体を初期化する KeInitializeGuardedMutex ルーチンを呼び出します。

スレッドは、次のいずれかの操作を行って、保護されたミューテックスを取得します。

  • KeAcquireGuardedMutex の呼び出し。 ミューテックスが既に別のスレッドによって取得されている場合、ミューテックスが使用可能になるまで、呼び出し元のスレッドの実行は中断されます。

  • KeTryToAcquireGuardedMutex を呼び出して、現在のスレッドを中断せずに、保護されたミューテックスを取得しようとします。 ミューテックスが取得されたかどうかに関係なく、ルーチンは直ちに戻ります。 KeTryToAcquireGuardedMutex は、呼び出し元のミューテックスを正常に取得した場合に TRUE を返します。それ以外の場合は FALSE を返します。

スレッドは 、KeReleaseGuardedMutex を呼び出して、 KeAcquireGuardedMutex または KeTryToAcquireGuardedMutex によって取得された保護されたミューテックスを解放します。

保護されたミューテックスを保持するスレッドは、保護された領域内で暗黙的に実行されます。 KeAcquireGuardedMutexKeTryToAcquireGuardedMutex は保護された領域に入り、 KeReleaseGuardedMutex はそれを終了します。 スレッドが保護されたミューテックスを保持している間は、すべての APC が無効になります。

コード パスがすべての APCs を無効にして実行することが保証されている場合、ドライバーは代わりに KeAcquireGuardedMutexUnsafeKeReleaseGuardedMutexUnsafe を使用して、保護されたミューテックスを取得して解放できます。 これらのルーチンは、保護された領域に入ったり終了したりせず、既に存在する保護されたリージョン内、または IRQL = APC_LEVELでのみ使用できます。

保護されたミューテックスを再帰的に取得することはできません。 既にガードされたミューテックスを保持しているスレッドが取得しようとすると、そのスレッドはデッドロックします。 保護されたミューテックスは、IRQL <= APC_LEVEL で実行されるコードでのみ使用できます。