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