Windows (正確には Win32) のカーネル モード ドライバーに相当するスレッド ローカル ストレージ (TLS) はありますか?
私が達成しようとしていること:
最終的に、ドライバーのディスパッチ ルーチン内から、他の多くの関数を呼び出す可能性があります (コールスタックが深い可能性があります)。処理中のリクエストに固有のコンテキスト情報を提供したいと考えています。つまり、すべての関数にパラメーターとして明示的に渡すことなく、呼び出されたすべての関数で表示されるはずの構造体、ポインターがあります。
静的/グローバルの使用は完璧なオプションではありません (マルチスレッド、同期オブジェクトなど)。
それがユーザーモードのコードである場合、そのような状況では明らかに TLS を使用します。TlsGetValue
しかし、私の知る限り、 /のようなカーネルモード関数はありませんTlsSetValue
。そして、これは理にかなっています-これらの機能が機能するには、最初にプロセス全体のTLSインデックスを割り当てる必要があります. OTOH ドライバー コードは、特定のプロセスに限定されず、任意のスレッドで呼び出すことができます。
ただし、永続的なスレッド固有のストレージは実際には必要ありません。トップレベルの関数呼び出し用にスレッド固有のストレージが必要なだけです。
ハックな方法ではありますが、TLSを「実装」する方法を知っていると思います。TLS インデックスを割り当てる代わりに、常に定義済みのインデックス (index=0 など) を使用します。最上位関数で、保存されている TLS 値を保存し、必要な値で上書きします。完了すると、保存された値が復元されます。
幸いなことに、私は TLS が Win32 でどのように実装されているかを知っています。TIB
スレッドごとに構造体 (スレッド情報ブロック) があります。すべてのスレッドで、FS:[18h]
セレクターを使用してアクセスできます。にはTIB
、(とりわけ) TLS で使用される配列が含まれています。残りは非常に簡単です。
ただし、公式の API を使用して同様のことを実現したいと思います。
- 必要なものを実現するための公式のカーネルモード API はありますか?
- 私がやろうとしていることを避ける理由はありますか?再入に問題がある可能性があることはわかっています (つまり、一部のコードが私を呼び出し、TLS 値を上書きしてから、TLS に依存している可能性のある元のコードを最終的に呼び出します)。しかし、これは私の特定のケースでは不可能ですか?
- これを解決するための汚れの少ない方法はありますか?
前もって感謝します。
PS One は、理論的には SEH を使用する可能性があります (これには、スレッドごとの情報も格納されます)。つまり、最上位のコードを でラップし__try/__except
、コンテキスト情報が必要な場所で、いくつかのパラメーターを使用して継続可能な例外を発生させ、__except
ブロック内でパラメーターにコンテキスト情報を入力してから、実行を再開します。これは、文書化されていない機能を使用しない、100% 有効なプログラム フローです。しかし、パフォーマンスの複雑さは言うまでもなく、これは私にとって醜いハックのようです。