1. ホーム
  2. multithreading

[解決済み] ユーザーレベルのスレッドとカーネルがサポートするスレッドの違い?

2023-05-11 17:34:11

質問

このトピックに基づいていくつかのノートに目を通しましたが、一般的にスレッドについて理解しているものの ユーザー レベルとカーネル レベルのスレッドの違い .

プロセスは基本的に複数のスレッドまたは単一のスレッドで構成されていることは知っていますが、これらのスレッドは前述した2種類のスレッドなのでしょうか?

私の理解では、カーネルがサポートするスレッドは、ユーザーレベルのスレッドが利用できないシステムコールやその他の用途のためにカーネルにアクセスすることができます。

つまり、ユーザーレベルのスレッドは、プログラマーによって作成されたスレッドで、その状態のために通常実行できない操作を実行するためにカーネルサポートスレッドを利用するものなのでしょうか?

どのように解決するのですか?

編集部:質問が少しわかりにくかったので、2通りの方法で回答しています。

OS レベルのスレッドと Green Threads の比較

わかりやすくするために、私は通常、quot;Kernel-level threads" (以下の私のオリジナルの回答では "kernel threads" と混同しました) の代わりに "OS-level threads" または "native threads" と言っています。 OSレベルのスレッドはOSによって作成、管理されます。ほとんどの言語がスレッドをサポートしています。(C、最近のJavaなど)問題を防ぐのに100%の責任を負うことになるため、非常に使いにくいものです。いくつかの言語では、ネイティブのデータ構造 (ハッシュや辞書など) でさえ、追加のロック コードがなければ壊れてしまいます。

OS スレッドの反対語は グリーンスレッド であり、言語によって管理されます。このスレッドは言語によって様々な名前が付けられています(C言語ではコルーチン、Goではゴルーチン、Rubyではファイバーなど)。これらのスレッドは言語内部のみに存在し、OSには存在しません。言語がコンテキストスイッチを選択するため(つまり文の終わり)、微妙な競合状態(部分的にコピーされた構造体を見たり、ほとんどのデータ構造をロックする必要があるなど)を大量に防止することができます。プログラマはquot;blocking"コール(例. data = file.read() など)、しかし、言語はそれをOSへの非同期呼び出しに変換する。そして、この言語では その他 緑色のスレッドが結果を待っている間実行されます。

グリーンスレッドはプログラマにとってずっと単純ですが、その性能は様々です。多くのスレッドがある場合、グリーンスレッドは CPU と RAM の両方にとってより良いものになります。 一方、ほとんどのグリーンスレッド言語はマルチコアを活用することができません。(シングルコアのコンピュータや携帯電話はもう買えません!)。そして、悪いライブラリは、OSコールをブロックすることによって言語全体を停止させることができます。

両方の世界のベストは、1CPUあたり1つのOSスレッドと、OSスレッド上に魔法のように移動される多くのグリーンスレッドを持つことです。GoやErlangのような言語がこれを可能にします。

<ブロッククオート

ユーザーレベルのスレッドでは利用できないシステムコールや他の利用法

これは半分だけ真実です。しかし、言語には通常代替手段があるため、それに気づくことはありません。これらの置き換えはカーネルを呼び出しますが、あなたが考えるのとは少し違います。


カーネル スレッドとユーザー スレッドの比較

編集:これは私のオリジナルの回答ですが、ユーザー空間のスレッドとカーネルのみのスレッドについてであり、(後から考えると)おそらく質問ではなかったと思います。

ユーザー スレッドとカーネル スレッドはまったく同じものです。(/proc/ を見て、カーネル スレッドもそこにあることを確認すればわかります)。

ユーザースレッドとは、ユーザースペースコードを実行するものです。しかし、それはいつでもカーネル空間に呼び出すことができます。セキュリティ レベルを上げたカーネル コードを実行していても、まだ "ユーザー" スレッドと見なされます。

カーネル スレッドは、カーネル コードのみを実行し、ユーザー空間プロセスとは関連付けられていないものです。これらは、カーネルのみのデーモンであることを除けば、UNIX のデーモンと同じです。つまり、カーネルはマルチスレッドプログラムであると言えるでしょう。例えば、スワップ用のカーネルスレッドがあります。これは、すべてのスワップ問題を1つのストリームに"serialized"することを強制するものです。

ユーザースレッドが何かを必要とする場合、カーネルを呼び出し、カーネルはそのスレッドをスリーピングとしてマークします。その後、スワップ スレッドがデータを見つけ、ユーザー スレッドを実行可能としてマークします。その後、ユーザー スレッドは、何事もなかったかのようにカーネルからユーザーランドに戻ります。

実際には はすべて スレッドはカーネル空間で開始します。なぜなら clone() 操作はカーネル空間で行われるからです。(そして、ユーザー空間の新しいプロセスに「戻る」前に行うべきカーネル会計がたくさんあります)。