はい、オペレーティングシステムに関連する多くの資料を読みました。そして、私はまだ読んでいます。しかし、それらのすべてがプロセスとスレッドを「抽象的な」方法で記述しているようであり、そのため、その動作とロジックの組織化について多くの高レベルの調査が行われます。 私はそれらが何であるのか疑問に思っていますphysically?私の意見では、それらは単にメモリ内の「データ構造」ですプログラムの実行を容易にするためにカーネルコードによって維持および使用されます。たとえば、オペレーティングシステムは、一部のプロセスデータ構造(PCB)を使用して、特定のプログラムに割り当てられたプロセスの側面(優先度、アドレス空間など。よろしいですか?
通常、notepad.exeなどの実行可能ファイルを実行すると、単一のプロセスが作成されます。これらのプロセスは他のプロセスを生成する可能性がありますが、ほとんどの場合、実行する実行可能ファイルごとに1つのプロセスがあります。プロセス内には、多くのスレッドが存在する可能性があります。通常、最初は1つのスレッドがあり、通常はmain
関数であるプログラムの「エントリポイント」から始まります。命令は1つずつ順番に実行されます。たとえば、片手しか持っていない人のように、スレッドは次のスレッドに進む前に一度に1つの処理しか実行できません。
その最初のスレッドは追加のスレッドを作成できます。追加の各スレッドには独自のエントリポイントがあり、通常は関数で定義されます。プロセスは、その中で生成されたすべてのスレッドのコンテナーのようなものです。
これはかなり単純な説明です。もっと詳しく説明することもできますが、教科書にあるものとおそらく重複するでしょう。
編集:あなたは私の説明に多くの「通常」のものが含まれていることに気付くでしょう。時々劇的に異なることをするまれなプログラムがあるからです。
プロセスとスレッドの違いを理解するために最初に知っておく必要があるのは、プロセスは実行されない、スレッドは実行されるという事実です。
では、スレッドとは何ですか?最も近いのは、実行状態であることを説明します。たとえば、CPUレジスタ、スタック、ロットの組み合わせです。 any与えられた瞬間にデバッガに侵入することで、その証拠を見ることができます。何が見えますか?呼び出しスタック、一連のレジスタ。それだけです。それがスレッドです。
では、プロセスとは何でしょうか。まあ、それはスレッドを実行するための抽象的な「コンテナ」エンティティのようなものです。 OSが最初の概算に関係する限り、OSがいくつかのVMに割り当て、ファイルハンドル、ネットワークソケットなどの)システムリソースを割り当てるエンティティです&c。
彼らはどのように連携しますか? OSは、リソースを予約し、「メイン」スレッドを開始することで「プロセス」を作成します。そのスレッドは、さらにスレッドを生成できます。これらは1つのプロセス内のスレッドです。彼らは多かれ少なかれ、これらのリソースを何らかの方法で共有できます(たとえば、他の人の楽しみを損なうことがないようにロックが必要になる場合があります&c)。そこから、OSは通常、VM(そのプロセスに「属していない」メモリへのアクセス試行を検出して防止する)ことを「内部」で維持する責任があります。それらのスレッドをスケジュールして、「一度に1つだけではなく、いつでも」実行できるようにします。
スレッドとプロセスを非抽象的な方法で説明することがほとんど不可能である理由の1つは、それらがare抽象化であることです。
それらの具体的な実装は異なります途方もなく。
たとえば、ErlangプロセスとWindowsプロセスを比較します。Erlangプロセスは非常に軽量で、多くの場合400バイト未満です。最近のラップトップで1000万のプロセスを問題なく開始できます。彼らはvery早く起動し、彼らはvery早く死にます、そしてあなたは非常に短いタスクにそれらを使うことができると期待されています。すべてのErlangプロセスには、独自のガベージコレクターが関連付けられています。 Erlangプロセスは決してメモリを共有できません。
Windowsプロセスは非常に重いため、数百MiByteになることもあります。運がよければ、たぶん数千のサーバーを強力なサーバーで起動できます。彼らは立ち上がり、ゆっくりと死んでいきます。 Windowsプロセスは、IDE、テキストエディタ、ワードプロセッサなどのアプリケーションの単位であるため、通常、かなり長い時間(少なくとも数分)は存続すると予想されます。独自のアドレススペースがありますが、ガベージコレクターはありません。 Windowsプロセスはメモリを共有できますが、デフォルトでは共有しません。
スレッドも同様の問題です。x86上のNPTL Linuxスレッドは4 KiByteまで小さく、32ビットx86マシン上で800000+を開始することができます。このマシンは確かに数千、おそらく数万のスレッドで使用できます。 .NET CLRスレッドの最小サイズは約1 MiByteです。つまり、そのうちのわずか4000が32ビットマシンのアドレス空間全体を消費します。したがって、4000のNPTL Linuxスレッドは通常問題にはなりませんが、その前にメモリが不足するため、start 4000 .NET CLRスレッドすらできません。
OSプロセスとOSスレッドの実装方法も、オペレーティングシステムによって大きく異なります。主な2つのアプローチは次のとおりです。カーネルはプロセスのみを認識します。スレッドは、カーネルの知識がまったくないユーザースペースライブラリによって実装されます。この場合も、2つのアプローチがあります。1:1(すべてのスレッドが1つのカーネルプロセスにマップされます)またはm:n(mスレッドはnプロセスにマップされます。通常、m> n、多くの場合n == #CPU)。これは、スレッドが発明された後、多くのオペレーティングシステムで採用された初期のアプローチでした。ただし、通常は非効率的であると見なされ、ほとんどすべてのシステムで2番目のアプローチに置き換えられています。スレッドはカーネルに(少なくとも部分的に)実装されているため、カーネルは2つの異なるエンティティ、スレッドとプロセスを認識します。
3番目のルートとなるオペレーティングシステムの1つはLinuxです。 Linuxでは、スレッドはユーザースペースにもカーネルにも実装されていません。代わりに、カーネルは、タスクと呼ばれる両方スレッドとプロセス(および実際にはさらにいくつか)の抽象化を提供します。タスクはカーネルスケジュールエンティティであり、兄弟で共有するリソースとプライベートであるリソースを決定する一連のフラグを伴います。
これらのフラグの設定方法に応じて、スレッド(ほとんどすべてを共有)またはプロセス(システムクロック、ファイルシステム名前空間、ネットワーク名前空間、ユーザーID名前空間、プロセスID名前空間などのすべてのシステムリソースを共有)を取得します。しかし共有しないアドレス空間)。しかし、あなたはまた、いくつかの他のかなり興味深いものを手に入れることもできます。 BSDスタイルのjailを簡単に取得できます(基本的にはプロセスと同じフラグですが、ファイルシステムまたはネットワーク名前空間を共有しないでください)。または、他のOSが仮想化コンテナーまたはゾーンと呼ぶものを取得することもできます(刑務所のようですが、UIDおよびPID名前空間とシステムクロックを共有しないでください)。数年前からKVM(カーネル仮想マシン))と呼ばれるテクノロジーを使用して、本格的な仮想マシン(何も共有せず、プロセッサのページテーブルすら共有しない)を取得することもできます。これについてのことは、高度に調整された成熟したタスクスケジューラをカーネル内でこれらすべてのものに再利用できることです。Xen仮想マシンがよく批判されたものの1つは、スケジューラのパフォーマンスの低さでした。KVM開発者はXenよりもはるかに優れたスケジューラを備えており、最善のことは、1行のコードを記述する必要さえなかったことです!]
したがって、Linuxでは、スレッドとプロセスのパフォーマンスはWindowsや他の多くのシステムよりもはるかに近くなります。これは、Linuxでは実際には同じものだからです。つまり、使用パターンは大きく異なります。Windowsでは、通常、重みに基づいてスレッドとプロセスのどちらを使用するかを決定します。実際に共有したくない場合でも、プロセスを用意するか、スレッドを使用する必要がありますか。状態? Linux(通常はUnix全般)では、そのセマンティクスに基づいて決定します。実際に状態を共有するかどうかを決めますか?
1つの理由whyプロセスは、Unixの方がWindowsよりも軽い傾向がありますが、使用方法が異なります。Unixでは、プロセスは同時実行性と機能性の両方の基本単位です。同時実行を使用する場合は、複数のプロセスを使用します。アプリケーションを複数の独立した部分に分割できる場合は、複数のプロセスを使用します。すべてのプロセスは1つのことを正確に実行し、onlyは1つのことを実行します。単純な1行のシェルスクリプトでさえ、多くの場合、数十または数百のプロセスを伴います。アプリケーションは通常、多くの、しばしば短期間のプロセスで構成されています。
Windowsでは、スレッドは同時実行の基本単位であり、COMコンポーネントまたは.NETオブジェクトは機能の基本単位です。アプリケーションは通常、単一の長期実行プロセスで構成されています。
繰り返しますが、それらは非常に異なる目的で使用され、非常に異なる設計目標を持っています。どちらかが良いか悪いかというわけではありません。それらがso異なるだけで、共通の特性は非常に抽象的にしか記述できません。
スレッドとプロセスについて言えることは、ほとんど次のとおりです。
私はそれを言うでしょう:
プロセスには、メモリ空間、開いているファイル、...、および1つ以上のスレッドがあります。
スレッドは、システム上でプロセッサ上にスケジュールできる命令ストリームです。
以前にここで [〜#〜] so [〜#〜] に与えた詳細な回答を見てください。それは、プロセスとスレッドを維持する責任があるおもちゃのカーネル構造への洞察を与えます...
よろしくお願いします、トム。
プロセスは、プログラムの実行中に使用される一連のリソースのコンテナです。
プロセスには以下が含まれます。
つまり、プロセスには複数のスレッドを含めることができます。
プロセス自体はジョブにグループ化できます。ジョブはプロセスのコンテナであり、単一のユニットとして実行されます。
threadは、CPUでの命令の実行をスケジュールするためにウィンドウが使用するものです。すべてのプロセスには少なくとも1つあります。
私のWikiにはいくつかのページがあります。
物理的に:
プロセスは、所有する資格情報、スレッドリスト、およびオープンハンドルリストを維持する構造です
スレッドはcontext(つまり、保存されたレジスタセット+実行する場所)、プロセスの仮想アドレススペースにマップされるページを説明するPTEのセット、および所有者を含む構造です。
これはもちろん非常に単純化された説明ですが、重要な部分を理解しています。 LinuxとWindowsの両方での実行の基本単位はスレッドです-カーネルスケジューラはプロセスを気にしません(多く)。これが、LinuxでスレッドがPTEを別のプロセスと共有するプロセスである理由です。
スレッドは、あなたが言うように、オペレーティングシステムのスケジューラのメモリ構造です。スレッドは、メモリ内の一部の命令の開始をポイントし、スケジューラがそうする必要があると判断したときにこれらの命令を処理します。スレッドの実行中、ハードウェアタイマーが実行されます。目的の時間に達すると、割り込みが呼び出されます。この後、ハードウェアは現在のプログラムの実行を停止し、スケジューラの一部となる登録済みの割り込みハンドラー関数を呼び出して、現在のスレッドの実行が終了したことを通知します。
プロセスは、アプリケーションを実行するためにOSによって管理されるメモリ内の領域です。スレッドは、専用タスクを実行するためのプロセス内のメモリ内の小さな領域です。
この質問を正解する短い答えを出すのはちょっと難しいです。
そして、これをひどく間違って単純化するリスクがある場合、スレッドとプロセスはオペレーティングシステム/プラットフォームの概念であると言えます。裏では、シングルスレッドプロセスを定義することができます。
最近のオペレーティングシステムでは、各プロセスに独自のメモリ空間があります。共有メモリ(一部のOSのみがこれをサポートします)を除いて、オペレーティングシステムは、あるプロセスが別のプロセスのメモリ空間に書き込むことを禁止します。 Windowsでは、プロセスが試行すると一般保護違反が表示されます。
したがって、マルチスレッドプロセスはパッケージ全体であると言えます。そして、各スレッドは基本的に実行状態にすぎません。
したがって、スレッドが別のスレッドにプリエンプトされた場合(たとえば、ユニプロセッサシステム上)、オペレーティングシステムが行うべきことは、原則としてスレッドの実行状態を保存することだけです(スレッドに対して特別なことを行う必要があるかどうかはわかりません)。スタック)と別のものにロードします。
一方、プロセス全体を先取りすることは、想像できるほどコストがかかります。
編集:アイデアは、Javaのような抽象化されたプラットフォームにも適用されます。
プロセスとスレッドは抽象化です。それらについて、またはオペレーティングシステムの他の部分については、物理的なものは何もありません。これがソフトウェアと呼ばれる理由です。
コンピュータを物理的に見ると、 Turing Machine の動作をエミュレートする電子回路のごちゃごちゃになってしまいます。生のTruing Machineで何か便利なことをしようとすると、5分で脳がJell-Oに変わります。その不愉快な経験を回避するために、コンピューターの人々は、コンピューティングのさまざまな側面を区分する一連の抽象概念を開発しました。これにより、それをサポートする他のすべてのものについて心配する必要なく、興味のある抽象化のレベルに集中できます。いくつかのものは回路にキャストされています(例:加算器など)。これにより物理的になりますが、作業の大部分はセットの抽象化に基づいています。一般的なルールとして、私たちが使用する抽象化には、それらに対する何らかの形式の数学的基礎があります。これが、スタック、キュー、および「状態」がコンピューティングで非常に重要な役割を果たす理由です。これらの抽象化の周りには、それらの操作に基づいて推論するための十分に確立された数学のセットがあります。
重要なのは、ソフトウェアが常に「もの」の抽象的なモデルの複合に基づいていることを認識することです。それらの「もの」は必ずしも物理的なものに関連しているとは限らず、他の抽象化に関連している可能性が高いです。このため、テキストブックのどこにも、プロセスとスレッドの十分な「物理的」根拠を見つけることができません。
他の何人かの人々は、スレッドとプロセスが何であるかへのリンクと説明を投稿しましたが、それらのどれもが「物理的」なものを指し示していません。ご想像のとおり、これらは実際にはオペレーティングシステムのより大きなコンテキスト(つまり、より多くのデータ構造とルール...)内に存在する単なるデータ構造とルールのセットです。
ソフトウェアは玉ねぎのようなもので、レイヤーを重ねて重ねます。すべてのレイヤー(抽象)を剥がすと、何も残りません。しかし、玉ねぎはまだ非常に現実的です。
私は多くの答えを見ましたが、それらのほとんどはOS初心者にとって十分に明確ではありません。
現代のオペレーティングシステムでは、1つのプロセスに仮想CPU、仮想メモリ、仮想I/Oがあります。
仮想CPU:複数のコアがある場合、スケジューラーによる処理のためにプロセスに1つ以上のコアが割り当てられる可能性があります。
仮想I/O:I/Oはさまざまなプロセス間で共有される場合があります。複数のプロセスで共有できるキーボードの例のように。したがって、メモ帳に入力すると、デーモンとして実行されているキーロガーがすべてのキーストロークを保存している間にテキストが変化するのがわかります。したがって、プロセスはI/Oリソースを共有しています。
仮想メモリ: http://en.wikipedia.org/wiki/Virtual_memory リンクをたどることができます。
したがって、プロセスがスケジューラーによって実行状態から取り出されると、そのプロセスの状態はレジスターに格納された値を含み、そのスタックとヒープなどがデータ構造に保存されます。
したがって、プロセスをスレッドと比較すると、プロセスによって開始されたスレッドは、それを開始したプロセスに割り当てられた仮想I/Oと仮想メモリを共有しますが、仮想CPUは共有しません。したがって、同じ仮想メモリと仮想I/O buをすべて共有しているが、異なる仮想CPUを持つプロセスによって、複数のスレッドが開始されている可能性があります。
したがって、仮想メモリ空間がプロセスのスレッド間で共有されるため、静的に割り当てられた(スタック)場合も動的に割り当てられた(ヒープ)場合も、プロセスのリソースをロックする必要性を理解できます。
また、独自の仮想CPUを持つ各スレッドは、異なるコアで並行して実行でき、プロセスの完了時間を大幅に削減できます(メモリを適切に管理していて、複数のコアがある場合にのみ、削減が見られます)。
それがあなたが求めているものであるならば、それらはひもの物理的な断片ではありません。 ;)
私が理解しているように、オペレーティングシステム内のほとんどすべてが単なるデータです。最新のオペレーティングシステムは、仮想メモリアドレス変換、割り込み、メモリ保護など、いくつかのハードウェア要件に依存しています(ブート中に発生する多くのあいまいなハードウェア/ソフトウェアマジックがありますが、そのプロセスにはあまり詳しくありません)。これらの物理的な要件が整ったら、その他はすべてオペレーティングシステムの設計者に任されます。すべてが単なるデータのチャンクです。
それらが抽象的な方法でのみ言及されている理由は、それらが概念であることであり、それらはデータ構造として実装されますが、どのように実装する必要があるかについての普遍的な規則はありません。
これは、少なくともスレッド/プロセス自体には当てはまります。スケジューラと割り込みタイマーがないと、スレッド/プロセスはあまり効果がありません。
スケジューラは、オペレーティングシステムが次のスレッドを選択して限られた時間だけ実行するアルゴリズムであり、割り込みタイマーは、現在のスレッドの実行を定期的に中断して制御を渡すハードウェアの一部です。スケジューラ。
何かを忘れた場合:協調スレッディングしかない場合、上記は当てはまりません。協調スレッドは、次のスレッドに制御を積極的に譲らなければなりません。これは、あるスレッドが他のスレッドの結果をポーリングして醜くなり、最初のスレッドが譲るのを待ちます。
これらは、動作するために基盤となるオペレーティングシステムのサポートを必要としないため、他のスレッドよりもさらに軽量です。
Java世界に関するこの質問に答えようとしています。
プロセスはプログラムの実行ですが、スレッドはプロセス内の単一の実行シーケンスです。プロセスには複数のスレッドを含めることができます。スレッドは軽量プロセスと呼ばれることがあります。
例えば:
例1:JVMは単一のプロセスで実行され、JVMのスレッドはそのプロセスに属するヒープを共有します。そのため、複数のスレッドが同じオブジェクトにアクセスする場合があります。スレッドはヒープを共有し、独自のスタックスペースを持っています。これは、1つのスレッドによるメソッドの呼び出しとそのローカル変数が他のスレッドからスレッドセーフに保たれる方法です。ただし、ヒープはスレッドセーフではなく、スレッドセーフのために同期する必要があります。
例2:プログラムは、キーストロークを読み取って絵を描くことができない場合があります。プログラムはキーボード入力に完全に注意を払う必要があり、一度に複数のイベントを処理する機能がないと問題が発生します。この問題の理想的な解決策は、プログラムの2つ以上のセクションを同時にシームレスに実行することです。スレッドはこれを可能にします。ここで、絵を描くことはプロセスであり、キーストロークを読むことはサブプロセス(スレッド)です。
スレッドはプロセスによって制御され、プロセスはオペレーティングシステムによって制御されます
プロセスはスレッドのコンテナです。
プロセスは互いにメモリを共有しません-いわゆる「保護されたフラットモデル」で動作するため、スレッドは同じメモリを共有します。
Windowsでは、少なくともWin 3.1を通過すると、オペレーティングシステム(OS)には複数のプロセスが含まれ、それぞれに独自のメモリスペースがあり、OSなしで他のプロセスと対話することはできません。
各プロセスには、同じメモリ空間を共有する1つ以上のスレッドがあり、OSが他のスレッドと対話する必要はありません。
さて、「物理的には何ですか」という答えはまだ見ていません。だから私はそれを試してみる。
プロセスとスレッドは物理的なものではありません。これらはオペレーティングシステムの機能です。通常、コンピュータの物理コンポーネントはそれらについて認識していません。 CPUは、オペコードの順次ストリームのみを処理します。これらのオペコードはスレッドに属している可能性があります。次に、OSはトラップと割り込みを使用して制御を取り戻し、実行するコードを決定して別のスレッドに切り替えます。
プロセスは1つの完全なエンティティです。とexeファイルまたは1つのjvm。 exeファイルが別のスペースで再び実行される親プロセスの子プロセスが存在する場合があります。スレッドは、プロセスが実行、停止などのスレッドを制御している同じプロセスでの実行の個別のパスです。