18

私はこの分野の初心者です。

fork()、、、およびpthreadvfork()を学習しました。clone()

pthread_create()スレッドを作成することに気づきました。これは、を使用して新しいプロセスを作成するよりもオーバーヘッドが少なくなりますfork()。さらに、スレッドはファイル記述子、メモリなどを親プロセスと共有します。

しかし、いつfork()clone()pthreadよりも優れているのでしょうか。実例を挙げて説明してもらえますか?

前もって感謝します。

4

4 に答える 4

36

clone(2)は、主にスレッドの実装に使用されるLinux固有のシステムコールです(特に、に使用されます)。さまざまな引数を使用して、 fork(2)のような動作をすることもできます。直接使用する人はほとんどいません。pthreadライブラリを使用する方が移植性が高くなります。独自のスレッドライブラリ(Posixスレッドの競合)を実装している場合にのみ、syscallを直接呼び出す必要があります。これは非常に注意が必要です(特に、マシンで調整されたアセンブリコード化ルーチンでfutex(2) syscallを使用する必要があるためです。 、futex(7)を参照)。直接使用したくない、またはpthread_createclonecloneclone(2)clonefutexpthreadの方がはるかに簡単に使用できるためです。

(他のpthread関数では、 aのlibpthread.so後に内部で簿記を行う必要があります)clonepthread_create

Jonathonが答えたように、プロセスには独自のアドレス空間とファイル記述子セットがあります。また、プロセスはexecve syscallを使用して新しい実行可能プログラムを実行できます。このプログラムは、基本的にアドレススペース、スタック、および新しいプログラムを開始するためのレジスタを初期化します(ただし、ファイル記述子は、close-on-execフラグO_CLOEXECを使用しない限り、保持される場合があります。開く)。

Unixライクなシステムでは、すべてのinitプロセス(通常、pid 1の最初のプロセスを除く)はfork(または;のようなバリアントで作成されますが、のように動作するようvforkに使用することはできますが、使用したくありません)。clonefork

(技術的には、Linuxでは、無視できる奇妙な例外がいくつかあります。特に、カーネルプロセスまたはスレッド、およびカーネルによって開始されるまれなプロセスの開始など/sbin/hotplugです。)

forkおよびexecvesyscallは、Unixプロセスの作成の中心です(waitpidおよび関連するsyscallを使用)。

マルチスレッドプロセスにはpthread_create、すべて同じアドレス空間とファイル記述子を共有する複数のスレッド(通常はによって作成される)があります。同じアドレス空間内の同じデータを並行して処理する場合はスレッドを使用しますが、同期とロックに注意する必要があります。詳細については、pthreadチュートリアルをお読みください。

Advanced UnixProgrammingや(無料で入手可能な)AdvancedLinuxProgrammingのような優れたUnixプログラミングの本を読むことをお勧めします。

于 2012-07-26T05:28:57.943 に答える
14

(および会社の)長所と短所はfork、既存のプロセスのクローンである新しいプロセスを作成することです。

ご指摘のとおり、新しいプロセスの作成にはかなりのオーバーヘッドがあるため、これは弱点です。また、プロセス間の通信は、何らかの「承認された」チャネル(パイプ、ソケット、ファイル、共有メモリ領域など)を介して行われる必要があることも意味します。

これは、親と子の間の(はるかに)より大きな分離を提供するため、強みです。たとえば、子プロセスがクラッシュした場合、それを強制終了して、別のプロセスをかなり簡単に開始できます。対照的に、子スレッドが停止した場合、それを強制終了することはせいぜい問題があります。そのスレッドが排他的に保持しているリソースを特定することは不可能であるため、その後クリーンアップすることはできません。同様に、プロセス内のすべてのスレッドが共通のアドレススペースを共有しているため、問題が発生した1つのスレッドが他のすべてのスレッドで使用されているデータを上書きする可能性があります。したがって、その1つのスレッドを強制終了するだけでは、混乱をクリーンアップするのに必ずしも十分ではありません。 。

言い換えれば、スレッドの使用はちょっとした賭けです。コードがすべてクリーンである限り、単一のプロセスで複数のスレッドを使用することで、ある程度の効率を得ることができます。複数のプロセスを使用するとオーバーヘッドが少し増えますが、単一の問題が引き起こす可能性のあるダメージを制限し、メジャーに遭遇した場合にプロセスをシャットダウンして置き換えることが非常に簡単になるため、コードをかなり堅牢にすることができます問題。

具体的な例としては、Apacheはかなり良い例かもしれません。プロセスごとに複数のスレッドを使用しますが、(とりわけ)問題が発生した場合の損傷を制限するために、プロセスごとのスレッド数を制限し、同時に実行される複数の個別のプロセスを生成できます。適切なサーバーでは、たとえば、それぞれ8つのスレッドを持つ8つのプロセスがある場合があります。スレッドの数が多いと、ほとんどI / Oバウンドのタスクで多数のクライアントにサービスを提供できます。プロセスに分割すると、問題が発生した場合でも、突然完全に応答しなくなり、シャットダウンする可能性があります。多くを失うことなくプロセスを再開します。

于 2012-07-26T05:42:33.543 に答える
6

これらはまったく異なるものです。fork()新しいプロセスを作成します。pthread_create()同じプロセスのコンテキストで実行される新しいスレッドを作成します。

スレッドは、とりわけ、同じ仮想アドレス空間、メモリ(良いまたは悪い)、開いているファイル記述子のセットを共有します。

プロセスは(本質的に)互いに完全に分離されており、互いに変更することはできません。

あなたはこの質問を読むべきです:


たとえば、私がシェル(たとえばbash)の場合、のようなコマンドを入力するlsfork()、新しいプロセスに移動し、次に実行可能ファイルに移動exec()します。ls(そして、私wait()は子プロセスにいますが、それは範囲外になります。)これはまったく異なるアドレス空間で発生します。ls爆発した場合でも、私はまだ自分のプロセスで実行しているので、気にしません。

一方、私が数学プログラムであり、2つの100x100行列を乗算するように求められたとします。行列の乗算は驚異的並列の問題であることを私たちは知っています。だから、私はメモリに行列を持っています。それぞれが同じソース行列を操作するN個のスレッドを生成し、結果を結果行列の適切な場所に配置します。これらは同じプロセスのコンテキストで動作するため、互いのデータにスタンプが押されていないことを確認する必要があることを忘れないでください。Nが8で、8コアのCPUを使用している場合、マトリックスの各部分を同時に効果的に計算できます。

于 2012-07-26T05:22:15.353 に答える
0

fork()(およびファミリ)を使用したUNIXでのプロセス作成メカニズムは非常に効率的です。さらに、ほとんどのUNIXシステムはカーネルレベルのスレッドをサポートしていません。つまり、スレッドはカーネルによって認識されるエンティティではありません。したがって、このようなシステムのスレッドは、カーネルレベルでのCPUスケジューリングのメリットを享受できません。pthreadライブラリは、kerenlではなくプロセス自体を実行します。また、このようなシステムでは、pthreadはvfork()を使用して、軽量プロセスとしてのみ実装されます。したがって、スレッドを使用しても、そのようなシステムでの移植性以外には意味がありません。

私の理解によると、Sun-solarisとwindowsにはカーネルレベルのスレッドがあり、Linuxファミリはカーネルスレッドをサポートしていません。

プロセスパイプとUNIXdoaminソケットを使用すると、同期の問題がなく、非常に効率的なIPCになります。スレッドを実際に使用する理由と時期が明確になることを願っています。

于 2013-10-09T04:17:48.453 に答える