10

3 種類のスレッド (カーネル レベル、ユーザー レベル、ハイブリッド) のうち、C# (より一般的には .NET) が使用するのはどの種類ですか?

4

2 に答える 2

8

カーネルスレッド (1 : 1)

「カーネルスレッド」という用語は、カーネル空間で完全に実行される実際のスレッドを指すために使用することも、カーネルによってスケジュールされたユーザー空間のスレッドを指すこともできます。「カーネルがサポートする」スレッドという用語は後者を意味し、ユーザー空間で実行されるが、カーネルによって促進されるスレッドであり、通常はカーネルがスレッドをスケジュールすることを意味します。

カーネル スレッドには特権が与えられており、ユーザー モード スレッドに制限されていないものにアクセスできます。ウィキペディアの「Ring (コンピュータ セキュリティ) 」を参照してください。Windows では、ユーザー モードはリング 3 に対応し、カーネル モードはリング 0 に対応します。

ユーザーレベルのスレッド (N : 1)

「ユーザーレベルのスレッド」は通常、ユーザー空間から見えるスレッドを意味します。つまり、スレッド標準の「スレッドの作成」関数を呼び出すときに作成するものです。一般に、「ユーザーレベルのスレッド」という用語は、システムによる実装方法に関係なく、アプリケーション コードによって作成されるスレッドを意味するために使用されます。これは、カーネル サポートがほとんどまたはまったくない純粋なユーザー空間スレッドである場合もあれば、カーネルによってスケジュールされたスレッドである場合もあります。

ハイブリッド スレッディング (M : N) [WikiPedia]

M:N は、M 個のアプリケーション スレッドを N 個のカーネル エンティティ、つまり「仮想プロセッサ」にマップします。これは、カーネル レベル (「1:1」) とユーザー レベル (「N:1」) のスレッド化の間の妥協点です。一般に、「M:N」スレッド システムは、カーネル スレッドやユーザー スレッドよりも実装が複雑です。これは、カーネルとユーザー空間の両方のコードを変更する必要があるためです。M:N 実装では、スレッド ライブラリは、利用可能なスケジュール可能なエンティティでユーザー スレッドをスケジュールする役割を担います。これにより、システムコールが回避されるため、スレッドのコンテキスト切り替えが非常に高速になります。

.Net スレッドは、Win32 API を使用し、それを優れたフレームワークとしてラップするユーザーレベルのスレッドです!


詳細は次のとおりです。

于 2013-02-26T15:58:05.880 に答える
6

それはC#自体ではなく、ランタイム(CLR)次第です。

.Netは、次の2つのモードをサポートしていると見なすことができます。

  • ユーザーランドのみのスケジューリング(またはWindows UMS)。このモードでは、あるユーザーランドスレッドは、カーネルスレッドを実際に変更することなく、別のユーザーモードスレッドへのコンテキストスイッチを実行できます。このモードでは、コーディングのオーバーヘッドが大幅に増加しますが、カーネルレベルのコンテキストスイッチで貴重な10〜20マイクロ秒を節約できます。
  • ハイブリッドモデル(圧倒的に人気)。このモデルでは、マネージコードは、ファイルの読み取りなど、カーネルへのアクセスを必要とします。一連のAPIを介して、コードの実行はユーザーランドの.NET呼び出しから、Windows API、カーネル、ドライバー、HALレイヤー、および物理ドライブに移動します。そして、データをフェッチするコールスタックに戻ります。コンテキストスイッチがスレッドスケジューラによって開始されると、ユーザースレッドとカーネルスレッドが変更されます。

マネージコードにはカーネルモードで実行する権限がないため、直接カーネルモードのスレッド化は許可されていません。Windows APIのみを呼び出すことができ、WindowsAPIはカーネルモードに切り替わります。


Thread、、 -を使用する場合TaskThreadPoolCLRはハイブリッドモデルを使用します。CLRは、そのクラスを表す管理対象オブジェクトを作成するため、ハイブリッドモデルが使用されます。マネージコードはすべてユーザーランドで実行されます。ただし、スレッドプール内にあるかどうかに関係なく、fibberとして作成されていないすべてのスレッド(以下を参照)には、基盤となるカーネルデータ構造があります。カーネルデータ構造は、スレッドのカーネル状態(カーネルスレッドID、作成時間と終了時間、プロセスID、開始スレッドアドレス、セキュリティアクセストークン、多数のタイマー、CPUレジスタ、カーネルスタックなど)を保持するために使用されます。これらはすべて、コンテキストスイッチですが、約10-20 * 10^-6秒かかります。

C ++呼び出しのUmsセット( CreateUmsThreadContextUmsThreadYieldなど)のマネージラッパーを使用する場合-CLRはUMSモードを使用しようとします。ただし、これは、具体的かつ手動で操作するいくつかのスレッドにのみ固有です。アプリケーションは引き続きハイブリッドモデルを使用します。ユーザーモードでは、手動で選択されたスレッド(ファイバー)が相互に手動で生成されます。ただし、このモードでも、ある時点でOSタスクスケジューラがカーネルスレッドの切り替えを開始するため、UMSのスケジュールされたスレッドの実行にとらわれることはありません。

完全を期すために、

  • カーネルモードのスケジューリングは、カーネルからのみアクセスできる非常に低レベルのメカニズムです。つまり、OSの内部またはある種のドライバーを開発する場合にのみ、それを使用できるということです。このようなスケジューリングは使いにくく、間違いがあり、 OS全体がフリーズ/スタック/クラッシュ/ BSODされるか、他の予測できない状態に移行します。カーネルレベルのスレッド化には、膨大な開発とテストの作業が必要です。たとえば、Windowsタスクスケジューラまたはメモリ管理サービスは、カーネルモードのスケジューリングを使用します。高度なマルチスレッド環境で安定するように、これらのコンポーネントの作成にかかった時間を想像できますか?
于 2013-02-26T16:04:10.923 に答える