コマンドを直接実行することとバックグラウンドでコマンドを実行することを比較します。

コマンドを直接実行することとバックグラウンドでコマンドを実行することを比較します。

Ubuntuはdatepid 6913を使用して対話型bashシェルで実行されており、.traceを介して他の対話型bashシェルでそのbashシェルを追跡していますstrace

dateTraceを使って直接実行する方法を知りたいです。ここトレース出力の場合)と背景(参照)ここトレース出力の場合):

run を実行すると、date2番目のシェルで最初のシェル6913を追跡した結果は次のとおりです。

$ sudo strace -f -e trace=process -p 6913
[sudo] password for t: 
Process 6913 attached
clone(Process 12918 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 12918
[pid  6913] wait4(-1,  <unfinished ...>
[pid 12918] execve("/bin/date", ["date"], [/* 66 vars */]) = 0
[pid 12918] arch_prctl(ARCH_SET_FS, 0x7ff00c632740) = 0
[pid 12918] exit_group(0)               = ?
[pid 12918] +++ exited with 0 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 12918
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12918, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)

run を実行すると、date &2番目のシェルで最初のシェル6913を追跡した結果は次のとおりです。

$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(Process 12931 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 12931
[pid 12931] execve("/bin/date", ["date"], [/* 66 vars */]) = 0
[pid 12931] arch_prctl(ARCH_SET_FS, 0x7f530c5ee740) = 0
[pid 12931] exit_group(0)               = ?
[pid 12931] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12931, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 12931
wait4(-1, 0x7ffea6780718, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)

run を実行すると、echo $b &2番目のシェルで最初のシェル6913を追跡した結果は次のとおりです。

$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(Process 31319 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 31319
[pid 31319] exit_group(0)               = ?
[pid 31319] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=31319, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 31319
wait4(-1, 0x7ffea6780718, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)

run を実行すると、{ date; } &2番目のシェルで最初のシェル6913を追跡した結果は次のとおりです。

$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 31294
Process 31294 attached
[pid 31294] clone(Process 31295 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 31295
[pid 31294] wait4(-1,  <unfinished ...>
[pid 31295] execve("/bin/date", ["date"], [/* 67 vars */]) = 0
[pid 31295] arch_prctl(ARCH_SET_FS, 0x7f78b7f0b740) = 0
[pid 31295] exit_group(0)               = ?
[pid 31295] +++ exited with 0 +++
[pid 31294] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 31295
[pid 31294] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=31295, si_status=0, si_utime=0, si_stime=0} ---
[pid 31294] wait4(-1, 0x7ffea67811d8, WNOHANG, NULL) = -1 ECHILD (No child processes)
[pid 31294] exit_group(0)               = ?
[pid 31294] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=31294, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 31294
wait4(-1, 0x7ffea6780718, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)

質問:

  1. コマンドを実行する限り、date直接実行し、バックグラウンドで実行することは同じことを行うようです。

    コマンドを直接実行すると、元のbashシェル自体は6913で、コマンドはclone()12918複製されます。execve()

    バックグラウンドでコマンドを実行すると、元のbashシェル clone()自体が6913で、そのレプリカが12931execve()コマンドです。

    どちらもclone()一度だけ呼び出されます。それらの違いは何ですか?

  2. コマンドが外部か組み込みかは重要ではありません。たとえば、実行date&と実行はecho $b &両方とも一度呼び出されますclone()。なぜそのような違いがありますか?

  3. runningdate &とを比較してみてください{ date; } &。 Bash のマニュアルは中かっこがサブシェルを生成しないことを示しています。トレース出力が異なる理由:

    • トレース出力には1つのクローン(6913生成12931)とクローン12931date&しかありません。clone()execve() date
    • トレース出力には2つのクローン(6913が31294を生成し、31294が31295を生成)と最後のクローンが31295を生成します{ date; }&clone()clone()execve() date
  4. バックグラウンドで実行されるコマンド(例date&:)は親シェルの子シェルで実行されるため、親シェルのローカル変数にアクセスできますが、直接実行されるコマンドは(たとえば)サブシェルで実行されないためアクセスdateできます。ありません。親シェルのサブシェル。トレースされた出力を使用して違いを説明できますか?

    $ b=1
    $ { echo $b; } &
    [1] 31214
    1
    

    これはb環境変数ではなく親シェルのローカル変数です。子シェルは&親シェルのコピーから作成されるため、親シェルの値をミラーリングします。私は以下でこの例を作成しました。bb1もう一つバックグラウンドではなくコマンド置換を使用し、両方ともコマンドを実行するためのサブシェルを作成します。

関連情報