フォークと複製について少し混乱しています。私はすでにそれを見ました:
フォークはプロセスに使用され、クローンはスレッドに使用されます。
フォークは単にクローンを呼び出し、クローンはすべてのプロセスとスレッドに使用されます。
これは正しいですか?これら2つのシステムコールと2.6 Linuxカーネルの違いは何ですか?
答え1
fork()
元のUNIXシステムコールです。スレッドではなく新しいプロセスを作成するためにのみ使用できます。しかも携帯性が良い。
Linuxでは、clone()
新しい実行スレッドを作成するために使用できる新しい多機能システム呼び出しです。渡されたオプションに応じて、新しい実行スレッドはUNIXプロセス、POSIXスレッド、それらの間のセマンティクス、またはまったく異なるセマンティクス(他のコンテナなど)に従うことができます。メモリ、ファイル記述子、さまざまな名前空間、シグナルハンドラなどを共有するかコピーするかを決定するさまざまなオプションを指定できます。
親セットのシステム呼び出しなので、clone()
glibcのシステム呼び出しラッパー実装は実際に呼び出されますが、これはプログラマーが知る必要がない実装の詳細です。以前のバージョンとの互換性のため、実際のシステムコールはまだLinuxカーネルに存在します。しかし、非常に古いバージョンのlibcやglibc以外の他のlibcを使用するプログラムで使用できるため、重複しています。fork()
clone()
fork()
clone()
pthread_create()
スレッドを生成するPOSIX関数を実装するためにも使用されます。
移植可能なプログラムは代わりにfork()
andを呼び出す必要があります。pthread_create()
clone()
答え2
clone()
Linux 2.6には2つのことがあるようです。
システムコールがあります:
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
これが「clone()」で説明されていますman 2 clone
。
マニュアルページをよく読んで、次の内容を見ることができます。
It is actually a library function layered on top of the
underlying clone() system call.
明らかに、同じ名前の混乱したシステムコールの上にある「ライブラリ関数」を使用してスレッドを実装する必要があります。
私は小さなプログラムを書いた。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
pid_t cpid;
switch (cpid = fork()) {
case 0: // Child process
break;
case -1: // Error
break;
default: // parent process
break;
}
return 0;
}
使用法:コンパイルc99 -Wall -Wextra
して実行して、strace -f
ブランチシステムコールが実際に実行していることを確認します。strace
Linux 2.6.18システム(x86_64 CPU)からこれを取得します。
20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0) = ?
20098 exit_group(0)
出力には「フォーク」呼び出しは表示されませんstrace
。出力clone()
に表示される呼び出しには、strace
マニュアルページの複製とは非常に異なるパラメータがあります。child_stack=0
最初のパラメータが異なるためですint (*fn)(void *)
。
fork(2)
システムコールが次のように実装されているようです。本物 clone()
、「ライブラリ関数」の実装と同じですclone()
。これ本物 clone()
マニュアルページの複製とは異なるパラメータセットがあります。
fork()
簡単に言うと、との明らかに矛盾する両方のステートメントはclone()
正確です。しかし、関連する「クローン」は異なります。
答え3
fork()
システムコール用の特定のフラグのセットですclone()
。clone()
「プロセス」または「スレッド」を生成するのに一般的であるか、プロセスとスレッド間の奇妙なもの(たとえば、同じファイル記述子テーブルを共有する異なる「プロセス」)。
デフォルトでは、カーネルの実行コンテキストに関連する各情報「タイプ」について、その情報にエイリアスを指定またはclone()
コピーすることを選択できます。スレッドはエイリアスに対応し、プロセスはレプリケーションに対応します。 flagsの中間の組み合わせを指定すると、clone()
スレッドやプロセスではなく奇妙なものを作成できます。一般的にこれをしてはいけません。私の意見では、Linuxカーネルの開発中clone()
。