4

最新の WDK は、C++11 をサポートする Visual Studio 15 で使用するために提供されます。

ただし、どの程度の機能が使用できるかについてのドキュメントは見たことがありません。

明らかに、私はstd::threadandを使用しませんstd::mutexが、あまり明確ではありませんが、マジック スタティックスです。

Class * function()
{
     static Class myInstance;

     return &myInstance;
}

これはユーザーモードでスレッドセーフになりましたが、この構造がカーネルで機能するかどうかは不明です。

さらに懸念されるのは、C++11 より前のコードがカーネルで許容されていたということです (デストラクタが自明であると仮定すると)。

4

2 に答える 2

3

スイッチ /kernel msdn : /kernel (Create Kernel Mode Binary)に関するドキュメントをいくつか見つけました。これは、.obj がカーネル モード用であることをコンパイラに伝えるスイッチを説明しています。

これは、例外と RTTI の異なる動作を説明していますが、魔法の静的については言及していません。

単純なものの目に見える逆コンパイルから

Class * GetInstance()
{
   static Class instance;
   return &instance;
}

およびいくつかのユーザー モード テスト、コンパイラ

  1. スレッド ローカル コードを発行しません。
  2. ユーザーモードからのスレッドセーフ動作を提供しません。

編集

明確にするために。が指定されていない場合/kernel、マジック スタティックが機能し、静的初期化はスレッド セーフでした。このメカニズム (fs: を使用) は、カーネルには適用できませんでした。

/kernelコードはスレッドセーフではありませんでしたが、カーネル互換でした。(fs: への参照なし)

于 2016-03-09T18:43:36.617 に答える
0

カーネルを完全に書き直し、エクスポートされた名前の完全な新しい標準化を展開する(つまり、既存の実行可能ファイルをすべて破棄する) ことを計画していない限り、それはほとんど不可能だと思います。多くの C++ 機能は、実際には、コンパイラが存在するものに変換する必要があるメタ関数です。

これらの構造を別のプロセスに常駐させ、完全に不透明にすることstd::threadにより、カーネルリソースのラッパーとして実装できます(これは、「データ構造へのポインターへのポインターである可能性が最も高く、それが実際の HANDLE です」)。クライアントプログラム。

このような不透明度を保持するための関数呼び出しなどには、リンクする必要があるオブジェクト コードを生成しながら、すべての言語が依存できる標準の ABI (App. Binary インターフェイス) が必要です。

現在、オーバーロードがないため、C ABI は簡単です (_関数名に an を追加するだけです。これは、Windows カーネル ライブラリが採用する規則であり、すべてのコンパイラ開発者が Windows バージョンを作成するときに依存する必要があります)。しかし、C++ の名前マングリングは ... 独自のものです (システム レベルでどのように行う必要があるかについての定義はないため、すべてのコンパイラが独自に行います)。

そのため、信頼できる唯一のカーネルはエクスポートのみになりextern "C"ます。これは内部的に C++ で記述できますが、そのインターフェイスは、いずれにしてもプレーン C でなければなりません (それはclass* function();HANDLE CreateClass().

C++ 仕様レベルで標準 ABI を定義しても、それほど役に立たないことに注意してください。すべての C++ コンパイラは同じようにリンクしますが、他の言語に従う必要はありません。

また、システム レベルの ABI は、すべての言語がサポートする必要があるわけではないクライアント言語機能 (関数のオーバーロードなど) を必要としないように、十分に単純でなければなりません。

さらに複雑なことに、C++ にはテンプレートもあり、コンパイル中にコードをインスタンス化し、プロセス境界やカーネル バリアを越えて確実に実装することはできませvector<int>vector<double>。関数ですが、どうvecotr<foo>ですか?

vector<foo>自分のマシンでソフトウェアをコンパイルする際に、すべてのユーザーのシステム カーネルが存在するようにするにはどうすればよいですか? これはインストール時に実行できますが、通信インターフェイスの標準化がさらに必要になります。

カーネルは、アセンブラー レベルで存在する物理リソースのマネージャーです。それらを C で表現するのはほとんど簡単です。C++ の低レベル機能 (ほとんどは C と同じ) を使用する場合、C++ でそれらを表現することは些細なままですが、抽象化に立ち上がるとすぐに、標準化の欠如と複雑で重要な選択に直面します。また、それを実装する方法は、カーネルレベルでの使用法がそれほど明確に定義されていない可能性があるものに対する将来の制約に変換されます。


もちろん、原則として、カーネルの実装で内部的に C++ を使用することを禁止するものは何もありませんが、それによってリソース使用量全体の境界管理に問題が生じます。

実際のプロトコルは、「リソースへのアクセスを許可する」と「リソースを元に戻す」です。

クライアント プログラムは、これら 2 つの呼び出しを RAII クラスにラップし、すべての C++11 機能をそれに適用できますが、それを境界の反対側に移動するのはどうでしょうか? カーネルは を返すことができますwin::unique<something>か? ええと...そうではありません。プロセス内にないものを自分で破壊することはできないためです。その「samrtハンドル」には、カーネル関数への別の呼び出しをもたらすデストラクタがあります。o いずれの場合でも、カーネルには個別の Create/Get 機能と Delete/Relese 機能があります。

確かに、スマート ハンドルに関して C++ プログラムへの API を開発することはできますが、プログラムからカーネルへの通信は依然として単純な関数によって行われます (したがって、いずれにせよ、スマート ハンドルはすべてクライアント側で管理されます)。

同様に、スタックの巻き戻しは、呼び出しがすべて同期的であるが、作成/削除自体が同期的でない場合に機能します (それらは別の内部で呼び出されません)。それらは、YOUR スタックに存在する LOCAL オブジェクトを使用して、RAII パターンによって「同期」されます。しかし、*HPEN(逆参照に注意してください) 構造体はスタック内にありません: 別のプロセス (GDI ドライバー) 内にあるため、構築と破棄をsmart<HPEN>呼び出す必要があります。あなたの、カーネルではありません) が適切なポイントに到達します。CreatePenDeletePen

C++ //in kernel// は、同じカーネル呼び出し内でカーネル自体によって同期的に完全に構​​築および破棄されるオブジェクトに対して存在できます。その結果、クライアントによって何らかの形で使用されるために、カーネルの外に出ることはありません。これは確かに可能ですが、カーネルの目的は機能をエクスポートすることであり、エクスポートにはフラットな API が必要であるため、クライアント側の C++ ラッパーによって使用されるプレーンな C インターフェイスをエクスポートする C++ カーネルですぐに終了します。

その努力が正当化されるとは思えません。

于 2016-03-01T07:54:24.100 に答える