Ubuntuはdate
pid 6913を使用して対話型bashシェルで直接実行します。
$ date
Wed Mar 2 23:57:44 EST 2016
その間、次のコマンドを使用して、他の対話型bashシェルでbashシェル6913を追跡していますstrace
。
$ sudo strace -f -e trace=process -p 6913
Process 6913 attached
clone(Process 9098 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0x7f457c05ca10) = 9098
[pid 6913] wait4(-1, <unfinished ...>
[pid 9098] execve("/bin/date", ["date"], [/* 66 vars */]) = 0
[pid 9098] arch_prctl(ARCH_SET_FS, 0x7f40d6a4f740) = 0
[pid 9098] exit_group(0) = ?
[pid 9098] +++ exited with 0 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 9098
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9098, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffea6781518, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)
clone(Process 9099 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9099
[pid 9099] clone(Process 9100 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9100
[pid 9099] wait4(-1, <unfinished ...>
[pid 9100] execve("/bin/sed", ["sed", "s:\\([^/]\\)[^/]*/:\\1/:g"], [/* 66 vars */]) = 0
[pid 9100] arch_prctl(ARCH_SET_FS, 0x7f998bb03840) = 0
[pid 9100] exit_group(0) = ?
[pid 9100] +++ exited with 0 +++
[pid 9099] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9100
[pid 9099] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9100, si_status=0, si_utime=0, si_stime=0} ---
[pid 9099] wait4(-1, 0x7ffea6780c58, WNOHANG, NULL) = -1 ECHILD (No child processes)
[pid 9099] exit_group(0) = ?
[pid 9099] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9099, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 9099
wait4(-1, 0x7ffea6780f18, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)
私が見るには、出力が2つの部分に分けられるようです。
まず、bashシェル(6913)
clone()
自体が子プロセス9098を作成してから、子プロセス9098をexecve()
date
終了します。その後、bashシェル(6913)
clone()
自体は子プロセス(9099)を作成し、それ自体はclone()
子プロセス(9100)を作成し、その後子プロセス(9100)を作成しますexecve()
sed
。私の質問2番目の部分について:最後の2つと
clone()
最後の1つは、execve()
bashシェル6913から受信したSIGCHLDを処理するジョブに属していますか?これは何をしますか?9100を処理する理由は何ですか
execve()
sed
?ここで何をしているのsed
?プロセス9099がなぜそのプロセスではないのですか
execve()
sed
? 9099がclone()
9100を作成してから9100を作成するのはなぜですかexecve()
sed
?つまり、1つのクローン9099の代わりに2つの連続クローン9099と9100が必要なのはなぜですか?
コメントに返信:
$ echo $PROMPT_COMMAND
pwd2=$(sed "s:\([^/]\)[^/]*/:\1/:g" <<<$PWD)
$ echo $PS1
\u@\h:$pwd2\$
shel 6913で実行した後、トレースunset PROMPT_COMMAND
出力は次のようになります。
$ 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)
さて、上記の最初の2つの質問に答えがあります。 3番目の質問はまだよくわかりません。
答え1
clone(Process 9099 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9099
[pid 9099] clone(Process 9100 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f457c05ca10) = 9100
[pid 9099] wait4(-1, <unfinished ...>
[pid 9100] execve("/bin/sed", ["sed", "s:\\([^/]\\)[^/]*/:\\1/:g"], [/* 66 vars */]) = 0
この2つのフォーク(最新のLinuxシステムではシステムコールを使用してフォークが行われます)は、bashが変数をclone
評価するためです。PROMPT_COMMAND
pwd2=$(sed "s:\([^/]\)[^/]*/:\1/:g" <<<$PWD)
これらのフォークは、以前に受信したSIGCHLD信号と直接関係しません。
これバッシュマニュアル説明する:
Bashは、各デフォルトプロンプトを印刷する前に、PROMPT_COMMAND変数の値を確認します。 PROMPT_COMMANDが設定され、NULL以外の値を持つ場合、値はコマンドラインに入力されているかのように実行されます。
内部的にbashは最終的に呼び出します。解析と実行内容を評価しますPROMPT_COMMAND
。 Bashは、実行する必要があるフォークの数を最小限に抑えるように努めています。のような単純な文の場合、pwd2=$PWD
分岐は必要ありません。より複雑なステートメントの場合は、1つ以上のフォークを作成できます。あなたの場合、$( ... )
シェルフォーク(pid 9099)が発生し、角かっこ間のコマンドが評価されます。組み込みのユーティリティを呼び出すと、sed
別のフォークであるpid 9100が作成され、その後にexecveが続きます/bin/sed
。
sedはここで何をしていますか?
現在の作業ディレクトリの上のすべてのディレクトリ名から、最初の文字を除くすべての文字が切り捨てられるようです。