システム提供の Windows カーネル モード プロセスとスレッド マネージャーは、Windows オペレーティング システムでのプロセスとスレッドの実行方法を制御します。 このマネージャーを理解することは、スレッドの作成、プロセスの作成の監視、または共有リソースへのアクセスの同期を行う必要があるカーネル モード ドライバー開発者にとって不可欠です。
ObCallback ドライバーのサンプルでは、カーネル モード ドライバーでプロセスおよびスレッド通知ルーチンを使用する方法を示します。
プロセスとスレッドの概要
プロセスは、現在 Windows で実行されており、一意のプロセス ID (PID) によって識別されるソフトウェア プログラムです。 各プロセス内で、1 つ以上の スレッド は、プログラムのコードを実行する実際の実行単位を表します。 各スレッドには、そのプロセス内に一意のスレッド ID (TID) もあります。
スレッドは、プロセッサ時間を共有することでマルチタスクを有効にします。 単一プロセッサ コンピューターでは、複数のスレッドを割り当てることはできますが、一度に実行されるスレッドは 1 つだけです。 プロセッサはスレッドをすばやく切り替え、同時実行の錯覚を生み出します。 マルチプロセッサ システムでは、スレッドが異なるプロセッサで同時に実行されるときに、真の並列実行が発生します。
Windows カーネル モード プロセスとスレッド マネージャーは、プロセス内のすべてのスレッドの実行を処理します。 プロセッサが 1 つ以上あるかどうかにかかわらず、スレッドが処理される順序に関係なく、ドライバーが適切に動作するようにプロセスのすべてのスレッドが設計されていることを確認するには、ドライバー プログラミングに細心の注意を払う必要があります。
異なるプロセスのスレッドが同じリソースを同時に使用しようとすると、問題が発生する可能性があります。 Windows には、この問題を回避するためのいくつかの手法が用意されています。 異なるプロセスのスレッドが同じリソースに触れないようにする手法は 、同期と呼ばれます。 同期の詳細については、「 同期手法」を参照してください。
プロセスとスレッド マネージャーへの直接インターフェイスを提供するルーチンには、通常、"Ps" という文字が付きます。たとえば、 PsCreateSystemThread です。 カーネル DDI の一覧については、 Windows カーネルを参照してください。
プロセスおよびスレッド関連のコールバック関数を実装するためのベスト プラクティス
この一連のガイドラインは、次のコールバック ルーチンに適用されます。
- PCREATE_PROCESS_NOTIFY_ROUTINE
- PCREATE_PROCESS_NOTIFY_ROUTINE_EX
- PCREATE_THREAD_NOTIFY_ROUTINE
- PLOAD_IMAGE_NOTIFY_ROUTINE
- POB_PRE_OPERATION_CALLBACK
- POB_POST_OPERATION_CALLBACK
次のベスト プラクティスを使用します。
- ルーチンを短くシンプルに保ちます。
- プロセス、スレッド、またはイメージを検証するためにユーザー モード サービスを呼び出さないでください。
- レジストリ呼び出しを行わない。
- ブロックやプロセス間通信 (IPC) 関数呼び出しを行わない。
- 再入デッドロックが発生する可能性があるため、他のスレッドと同期しないでください。
-
システム ワーカー スレッドを使用して、特に次のような作業をキューに格納します。
- 他のプロセスを呼び出す低速 API または API。
- コア サービスのスレッドを中断する可能性があるブロック動作。
- システム ワーカー スレッドを使用する場合は、作業が完了するまで待機しないでください。 これにより、非同期的に完了する作業をキューに格納する目的が無効になります。
- カーネル モード スタックの使用に関するベスト プラクティスを考慮してください。 例については、「ドライバーが カーネル モード スタックを使い切れないようにする方法 」と「 主要なドライバーの概念とヒント」を参照してください。
サブシステム プロセス
Windows 10 以降では、Windows Subsystem for Linux (WSL) を使用すると、ユーザーは他の Windows アプリケーションと共に Windows 上でネイティブ Linux ELF64 バイナリを実行できます。 WSL アーキテクチャと、バイナリを実行するために必要なユーザー モードとカーネル モードのコンポーネントの詳細については、 Linux 用 Windows サブシステム に関するブログの投稿を参照してください。
コンポーネントの 1 つは、変更されていないユーザー モードの Linux バイナリ (/bin/bash など) をホストするサブシステム プロセスです。 サブシステム プロセスには、プロセス環境ブロック (PEB) やスレッド環境ブロック (TEB) など、Win32 プロセスに関連付けられているデータ構造は含まれません。 サブシステム プロセスの場合、システム呼び出しとユーザー モードの例外は、ペアになっているドライバーにディスパッチされます。
サブシステム プロセスをサポートするためにプロセスおよびスレッド マネージャー ルーチンに対する変更を次に示します。
WSL 型は、SUBSYSTEM_INFORMATION_TYPE列挙型の SubsystemInformationTypeWSL 値によって示されます。 ドライバーは 、NtQueryInformationProcess と NtQueryInformationThread を呼び出して、基になるサブシステムを特定できます。 これらの呼び出しは、WSL の SubsystemInformationTypeWSL を返します。
他のカーネル モード ドライバーは、 PsSetCreateProcessNotifyRoutineEx2 呼び出しを通じてコールバック ルーチンを登録することで、サブシステム プロセスの作成/削除に関する通知を受け取ることができます。 スレッドの作成/削除に関する通知を取得するために、ドライバーは PsSetCreateThreadNotifyRoutineEx を呼び出し、通知の種類として PsCreateThreadNotifySubsystems を 指定できます。
PS_CREATE_NOTIFY_INFO構造体は、Win32 以外のサブシステムを示す IsSubsystemProcess メンバーを含むように拡張されました。 FileObject、ImageFileName、CommandLine などの他のメンバーは、サブシステム プロセスに関する追加情報を示します。 これらのメンバーの動作については、 SUBSYSTEM_INFORMATION_TYPEを参照してください。