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)
제가 보기에는 출력이 두 부분으로 나누어질 수 있는 것 같습니다.
먼저 bash 쉘(6913)
clone()
자체가 하위 프로세스 9098을 생성한 다음 하위 프로세스 9098이execve()
date
종료됩니다.그 후, bash 쉘(6913)
clone()
자체는 자식 프로세스(9099)를 생성하고, 그 후clone()
자체적으로 자식 프로세스(9100)를 생성하고, 그 다음 자식 프로세스(9100)를 생성합니다execve()
sed
.내 질문두 번째 부분에 관해서 :마지막 두 개와
clone()
마지막 하나는execve()
bash 쉘 6913에서 수신한 SIGCHLD를 처리하는 작업에 속합니까? 이 작업은 무엇을 합니까?9100을 처리하는 이유는 무엇입니까
execve()
sed
? 여기서 뭐 하는 거야sed
?프로세스 9099가 왜 해당 프로세스가 아닌가
execve()
sed
? 9099가clone()
9100을 만든 다음 9100을 만드는 이유는 무엇입니까execve()
sed
? 즉, 하나의 클론 9099 대신 두 개의 연속 클론 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)
이제 위의 처음 두 질문에 답이 있습니다. 세 번째 질문은 아직 잘 모르겠습니다.
답변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
이 두 포크(최신 Linux 시스템에서는 시스템 호출을 사용하여 포크가 수행됨)는 bash가 변수를 clone
평가하기 때문입니다 .PROMPT_COMMAND
pwd2=$(sed "s:\([^/]\)[^/]*/:\1/:g" <<<$PWD)
이러한 포크는 이전에 수신된 SIGCHLD 신호와 직접적인 관련이 없습니다.
이것배쉬 매뉴얼설명하다:
Bash는 각 기본 프롬프트를 인쇄하기 전에 PROMPT_COMMAND 변수의 값을 확인합니다. PROMPT_COMMAND가 설정되고 Null이 아닌 값을 갖는 경우 값은 명령줄에 입력된 것처럼 실행됩니다.
내부적으로 bash는 궁극적으로 호출합니다.구문 분석 및 실행내용을 평가합니다 PROMPT_COMMAND
. Bash는 수행해야 하는 포크 수를 최소화하려고 노력합니다. 와 같은 간단한 명령문의 경우 pwd2=$PWD
분기가 필요하지 않습니다. 더 복잡한 명령문의 경우 하나 이상의 포크를 만들 수 있습니다. 귀하의 경우에는 $( ... )
쉘 포크(pid 9099)가 발생하고 대괄호 사이의 명령이 평가됩니다. 내장되지 않은 유틸리티를 호출하면 sed
또 다른 포크인 pid 9100이 생성되고 그 뒤에 execve 가 옵니다 /bin/sed
.
sed는 여기서 무엇을 하고 있나요?
현재 작업 디렉터리 위의 모든 디렉터리 이름에서 첫 번째 문자를 제외한 모든 문자가 잘리는 것 같습니다.