exec bash 組み込み関数は内部的にどのように動作しますか?

exec bash 組み込み関数は内部的にどのように動作しますか?

からこれlink exec bash 組み込みコマンドについて次の情報が得られます。

コマンドが指定された場合、シェルを置き換える新しいプロセスを作成する必要はありません。

シェルを正確にどのように置き換えるのでしょうか (つまり、内部的にはどのように動作するのでしょうか)?exec*()システム コールは同じように動作しますか?

答え1

はい、exec組み込み関数は、最終的にはシステム コール ファミリの 1 つを使用します。通常のコマンドの実行も同様です。 を使用すると、最初にシステム コールを使用して新しいプロセスを作成せず、結果として新しいコマンドがシェルを置き換えてしまうというexec*()だけです。execfork()

答え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/sleepaccess()execve()execve()sleepnanosleep()sleepsleepbash

証拠:

別のウィンドウで、 を使ってプロセスを監視しました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 秒かかります)。

関連情報