Linux / Unixベースのオペレーティングシステムでは、フォークを理解するのが良いことがわかります。 およびvfork システムコール、それらの動作、使用方法、およびそれらの違い。これらと一緒に待つ およびexec システムコールは、プロセスの生成やその他のさまざまな関連タスクに使用されます。
これらの概念のほとんどは、プログラミング例を使用して説明されています。この記事では、fork、vfork、exec、およびwaitシステムコールとは何か、それらを区別する文字、およびそれらをより適切に使用する方法について説明します。
fork()
fork(): 子プロセスを作成するためのシステムコール。
[email protected] ~}$ man fork
これにより、フォークの用途、構文、および必要なすべての詳細が記載された出力が生成されます。
forkシステムコールに使用される構文は次のとおりです。
pid_t fork(void);
Forkシステムコールは、 pid(プロセスID)のみが親プロセスと異なる子を作成します およびppid(親プロセスID) 。リソース使用率はゼロに設定されます。ファイルロックと保留中のシグナルは継承されません。 (Linuxでは、「fork」は「 copy-on-write()」として実装されます。 「)。
注:- 「コピーオンライト ”-> fork()システムコールが呼び出されるたびに、親プロセスに関連するすべてのページ(メモリ)のコピーが作成され、子プロセスのオペレーティングシステムによって別のメモリ位置にロードされます。ただし、これはすべての場合に必要なわけではなく、一部のプロセスがこのアドレス空間またはメモリ領域に書き込む場合にのみ必要になる可能性があり、その後、個別のコピーのみが作成/提供されます。
戻り値 :-子プロセスのPID(プロセスID)は、実行の親スレッドで返され、「ゼロ 」は子の実行スレッドで返されます。以下は、forkシステムコールがどのように機能するかを説明するcプログラミングの例です。
[email protected] ~}$ vim 1_fork.c #include<stdio.h> #include<unistd.h> Int main(void) { printf("Before fork\n"); fork(); printf("after fork\n"); } [email protected] ~}$ [email protected] ~}$ cc 1_fork.c [email protected] ~}$ ./a.out Before fork After fork [email protected] ~}$
システムコールが行われるたびに、UNIX/Linuxマシンの舞台裏で行われることがたくさんあります。
まず、コンテキストスイッチがユーザーモードからカーネル(システム)モードに切り替わります。これは、使用しているプロセスの優先順位とunix/linuxオペレーティングシステムに基づいています。上記のCのサンプルコードでは、コンテキストのエントリである「{」の開始中括弧と、コンテキストを終了するための「}」の終了中括弧を使用しています。次の表は、コンテキストの切り替えを非常に明確に説明しています。
vfork()
vfork –>子プロセスを作成し、親プロセスをブロックします。
注:-vforkでは、シグナルハンドラーは継承されますが、共有されません。
[email protected] ~}$ man vfork
これにより、vforkの用途、構文、および必要なすべての詳細が記載された出力が生成されます。
pid_t vfork(void);
vfork vforkによって作成されたプロセスがvforkの戻り値pを格納するために使用されるタイプpid_tの変数以外のデータを変更するか、_exit()またはexecの1つを呼び出す間に他の関数を呼び出す場合、動作が未定義であることを除いて、forkと同じです。 ()家族。
注: vforkは、クローンの特殊なケースと呼ばれることもあります。
以下は、vfork()のCプログラミング例です。
[email protected] ~}$ vim 1.vfork.c #include<stdio.h> #include<unistd.h> Int main(void) { printf("Before fork\n"); vfork(); printf("after fork\n"); } [email protected] ~}$ vim 1.vfork.c [email protected] ~}$ cc 1.vfork.c [email protected] ~}$ ./a.out Before vfork after vfork after vfork a.out: cxa_atexit.c:100: __new_exitfn: Assertion `l != NULL' failed. Aborted
注: –前に説明したように、多くの場合、vforkシステムコールの動作は予測できません。上記の場合と同様に、1回前と2回後に印刷されましたが、_exit()関数を使用して呼び出しを中止しました。特に明記されていない限り、forkシステムコールを使用し、vforkの使用はできるだけ避けた方がよいでしょう。
fork()とvfork()の違い
Vfork() 動作については、以下のプログラムで詳しく説明しています。
[email protected] ~}$ cat vfork_advanced.c #include <sys/types.h> #include <unistd.h> #include <stdio.h> int main() { int n =10; pid_t pid = vfork(); //creating the child process if (pid == 0) //if this is a chile process { printf("Child process started\n"); } else//parent process execution { printf("Now i am coming back to parent process\n"); } printf("value of n: %d \n",n); //sample printing to check "n" value return 0; } [email protected] ~}$ cc vfork_advanced.c [email protected] ~}$ ./a.out Child process started value of n: 10 Now i am coming back to parent process value of n: 594325573 a.out: cxa_atexit.c:100: __new_exitfn: Assertion `l != NULL' failed. Aborted
注: ここでも、vforkの結果が定義されていないことを確認します。 「n」の値は、最初に10として出力されましたが、これは予想どおりです。しかし、次回の親プロセスでは、ガベージ値が出力されました。
wait()
wait()システムコールは、子が終了するまで、または現在のプロセスを終了するかシグナルハンドラーを呼び出すアクションのシグナルが配信されるまで、現在のプロセスの実行を一時停止します。
pid_t wait(int * status);
以下のように待機に関連する他のシステムコールがあります
1) waitpid() :pid引数で指定された子が終了するまで、またはシグナルが配信されるまで、現在のプロセスの実行を一時停止します。
pid_t waitpid (pid_t pid, int *status, int options);
2) wait3() :子が終了するまで、またはシグナルが配信されるまで、現在のプロセスの実行を一時停止します。
pid_t wait3(int *status, int options, struct rusage *rusage);
3) wait4() :wait3()と同じですが、pid_tpid値が含まれます。
pid_t wait3(pid_t pid, int *status, int options, struct rusage *rusage);
exec()
exec() 関数またはsys呼び出しのファミリーは、現在のプロセスイメージを新しいプロセスイメージに置き換えます。
execlのような関数があります 、 execlp 、 execle 、 execv 、 execvp およびexecvpe ファイルの実行に使用されます。
これらの関数は、引数リストを表すnullで終了する文字列へのポインタの配列の組み合わせです。これには、いくつかの環境変数の組み合わせを含むパス変数があります。
exit()
この関数は、通常のプロセス終了に使用されます。プロセスのステータスは、将来の参照用にキャプチャされます。他にも同様の関数がありますexit(3) および_exit()。 、使用またはキャプチャすることに関心のある既存のプロセスに基づいて使用されます。
結論:-
これらすべてのシステムコール/関数の組み合わせは、プロセスの作成、実行、および変更に使用されます。これらは、「シェル」スポーン関数のセットとも呼ばれます。結果と動作を念頭に置いて、これらの関数を慎重に使用する必要があります。