つまり、シェル内で実行可能ファイルを実行すると、シェルはそれを子プロセスにフォークし、その後 exec を実行して実行可能ファイルのプログラムとデータ メモリを取得します。したがって、シェルが閉じられたり終了したりすると、関連するすべての子プロセスも強制終了されます。
Linuxではすべてのプロセスがfork() exec()で作成されると読みました。興味があり、アプリケーションのアイコンをダブルクリックして起動するたびに、どのプロセスがそれをfork() exec()するのか疑問に思いました。OSのプロセスだと理解していますが、どのプロセスがfork() exec()するのか疑問に思いました。
ありがとう!
答え /sbin/upstartまで追跡しました
答え1
まず、少し用語。
実行可能ファイルはシステム内の単純なファイルです。プロセスは実行可能ファイルに埋め込まれたプログラムを実行するものです。
あなたは正しい実行ファイルが起動される方法:
- 親プロセス(すでに実行中)
fork
s 自体が実行され、その時点から 2 つの実行フローが発生します。1 つは親プロセスで実行され、もう 1 つは新しいプロセスで実行されます。 - 新しい(子)プロセスは、実行ファイルのプログラムを実行するために自分自身をミュートします。これは、システムコールの
exec
家族。
実行可能アイコンをダブルクリックするグラフィカル インターフェイスを例にとると、基本的に次のソース コードを使用して、クリックしたアイコンを表示するプロセスから実行可能ファイルがフォークされます。
const char *exe_path = taken_from_icon();
int pid = fork();
if(pid == 0)
{
// I am the new child
execl(exe_path, exe_path, NULL);
// exec only return in case of failure
exit(EXIT_FAILURE);
}
// I am the graphical interface,
// Continue and wait for another clic
しかし死と親子関係子供のことは、あなたが言う通りではありません。
基本的に、親プロセスがまだ生きている場合、子プロセスは父プロセスの子です (そうです!-)。子プロセスの PPID (親プロセス ID) は、それをフォークしたまだ生きているプロセスに設定されます。
親プロセスが終了すると状況は変わります。子プロセスは存続しますが、その PPID はまだ存続している祖父母プロセスに設定されます。init
プロセスが終了することは決してないので、常に 1 つ存在します。
シェル自体が死ぬとシェルの子供も死ぬというのは特別なことです。それには 2 つの理由があると思います。
1つ目は、シェルは通常、フォークしたPIDのリストを保持しています。シェルが終了すると、それらすべてが削除されます。主要なシェルには、
disown
このリストから子を削除して、シェルが終了したときに子を生き残らせる組み込みコマンドがあります。bash マニュアルページ:デフォルトでは、シェルは SIGHUP を受信すると終了します。終了する前に、対話型シェルは実行中または停止中のすべてのジョブに SIGHUP を再送信します。停止中のジョブには、SIGHUP を確実に受信できるように SIGCONT が送信されます。シェルが特定のジョブにシグナルを送信しないようにするには、組み込みの disown を使用してジョブ テーブルからそのジョブを削除するか (以下のシェル組み込みコマンドを参照)、disown -h を使用して SIGHUP を受信しないようにマークする必要があります。
2 番目: シェルの子プロセスは通常、標準入力、標準出力、および標準エラー出力をパイプ経由でシェル自体に接続します。シェルが子プロセスの標準出力の使用を停止した場合 (多くの場合、印刷するため)、またはパイプの端を閉じた場合、子プロセスは標準出力への書き込みに失敗し、ブロックまたは強制終了する可能性があります。