からこれlink exec bash 組み込みコマンドについて次の情報が得られます。
コマンドが指定された場合、シェルを置き換える新しいプロセスを作成する必要はありません。
シェルを正確にどのように置き換えるのでしょうか (つまり、内部的にはどのように動作するのでしょうか)?exec*()
システム コールは同じように動作しますか?
答え1
はい、exec
組み込み関数は、最終的にはシステム コール ファミリの 1 つを使用します。通常のコマンドの実行も同様です。 を使用すると、最初にシステム コールを使用して新しいプロセスを作成せず、結果として新しいコマンドがシェルを置き換えてしまうというexec*()
だけです。exec
fork()
答え2
strace
実行中のインスタンスで を実行しましたbash
。次に、 コマンド を呼び出しましたexec sleep 100
。何が起こったか見てみましょう。
access("/bin/sleep", X_OK) = 0
...
execve("/bin/sleep", ["sleep", "100"], [/* 14 vars */]) = 0
...
nanosleep({100, 0},
...
exit_group(0) = ?
ご覧のとおり、sleep
通常の方法で呼び出した場合とほぼ同じように実行されます。システム コールでbash
実行権限 ( X_OK
) が付与されているかどうかを確認します。次に、ファイル名で指定されたプログラムを実行します。システム コールの後、プロセスを制御します。次の処理を実行します。また、同じ pid を保持します。終了すると、プロセスも終了します。または、もう実行されていないかどうか。/bin/sleep
access()
execve()
execve()
sleep
nanosleep()
sleep
sleep
bash
証拠:
別のウィンドウで、 を使ってプロセスを監視しましたps
。コマンドを実行する前は次のようになっていました。
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 -bash
そして、走っている間:
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 sleep 100
sleep
プロセスが終了すると消えてしまいました。
通常通りに実行すると何が起こりますか?
access("/bin/sleep", X_OK) = 0
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f6c9fd089d0) = 19261
...
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 19261
...
--- SIGCHLD (Child exited) @ 0 (0) ---
実行権限がチェックされます。次に、子プロセスが作成されますclone()
。bash
インスタンスはバックグラウンド プロセス グループに含まれ、sleep
フォアグラウンド プロセス グループに含まれます。最後に、呼び出しはwait4()
子プロセスが終了するまで待機します (これには 100 秒かかります)。