fork()
オリジナルの UNIX システム コールです。スレッドではなく、新しいプロセスを作成するためにのみ使用できます。また、ポータブルです。
Linux では、clone()
実行の新しいスレッドを作成するために使用できる、新しい汎用性の高いシステム コールです。渡されたオプションに応じて、実行の新しいスレッドは、UNIX プロセス、POSIX スレッド、その中間、またはまったく異なるもの (別のコンテナーなど) のセマンティクスに従うことができます。メモリ、ファイル記述子、さまざまな名前空間、シグナル ハンドラーなどを共有またはコピーするかどうかを決定する、あらゆる種類のオプションを指定できます。
clone()
以降 fork()
の実装であるスーパーセット システム コールです。 glibc のシステム コール ラッパーは実際に clone()
を呼び出します ですが、これはプログラマーが知る必要のない実装の詳細です。実際の fork()
システム コールは、非常に古いバージョンの libc や glibc 以外の別の libc を使用するプログラムが使用する可能性があるため、冗長になっていますが、下位互換性のために Linux カーネルにまだ存在しています。
clone()
pthread_create()
の実装にも使用されます スレッドを作成するための POSIX 関数。
移植可能なプログラムは fork()
を呼び出す必要があります および pthread_create()
、 clone()
ではありません .
clone()
が 2 つあるようです Linux 2.6 に浮かんでいるもの
システムコールがあります:
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
これは man 2 clone
を実行して記述された "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
に「fork」呼び出しが表示されない 出力。 clone()
strace
に表示される呼び出し output には、man-page-clone とは非常に異なる引数があります。 child_stack=0
最初の引数が int (*fn)(void *)
とは異なるため .
fork(2)
システム コールは real の観点から実装されています clone()
、「ライブラリ関数」のように clone()
が実装されています。 本物 clone()
man-page-clone とは異なる一連の引数があります。
単純に言えば、fork()
についてのあなたの明らかに矛盾した声明の両方 と clone()
は正しい。ただし、関連する「クローン」は異なります。
fork()
システムコール clone()
への特定のフラグセットです . clone()
「プロセス」または「スレッド」、またはプロセスとスレッドの間のどこかにある奇妙なもの (たとえば、同じファイル記述子テーブルを共有する異なる「プロセス」) を作成するのに十分一般的です。
基本的に、カーネル内の実行コンテキストに関連付けられたすべての「タイプ」の情報について、clone()
その情報をエイリアシングするかコピーするかを選択できます。スレッドはエイリアシングに対応し、プロセスはコピーに対応します。 clone()
に中間フラグの組み合わせを指定することで 、スレッドやプロセスではない奇妙なものを作成できます。通常はこれを行うべきではありません。Linux カーネルの開発中に、clone()
のような一般的なメカニズムを許可するかどうかについて議論があったと思います。 .