우분투에서는 date
pid 6913을 사용하는 대화형 bash 쉘에서 실행 중이며, .trace를 통해 다른 대화형 bash 쉘에서 해당 bash 쉘을 추적하고 있습니다 strace
.
date
Trace를 이용하여 직접 실행하는 방법을 알고 싶습니다 .여기추적 출력의 경우) 및 배경(참조여기추적 출력의 경우):
run 을 실행하면 date
두 번째 셸에서 첫 번째 셸 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 &
두 번째 셸에서 첫 번째 셸 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 &
두 번째 셸에서 첫 번째 셸 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; } &
두 번째 셸에서 첫 번째 셸 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)
질문:
명령을 실행하는 한
date
직접 실행하고 백그라운드에서 실행하는 것은 동일한 작업을 수행하는 것 같습니다.명령을 직접 실행하는 경우 원래 bash 셸 자체는 6913 이고 명령은
clone()
12918 복제됩니다 .execve()
백그라운드에서 명령을 실행하면 원래 bash 셸
clone()
자체가 6913이고 그 복제본이 12931execve()
명령입니다.둘 다
clone()
한 번만 호출됩니다. 그들 사이의 차이점은 무엇입니까?명령이 외부인지 내장인지는 중요하지 않습니다. 예를 들어 실행
date&
과 실행은echo $b &
모두 한 번 호출됩니다clone()
. 왜 그런 차이가 있습니까?running
date &
과 를 비교해 보세요{ date; } &
. Bash 매뉴얼에는 중괄호가 하위 쉘을 생성하지 않는다고 나와 있습니다. 추적 출력이 다른 이유:- 추적 출력에는 단 하나의 클론(6913 생성 12931)과 클론 12931
date&
만 있습니다 .clone()
execve()
date
- 추적 출력에는 두 개의 클론(6913이 31294를 생성하고, 31294가 31295를 생성)과 마지막 클론이 31295가
{ date; }&
있습니다 .clone()
clone()
execve()
date
- 추적 출력에는 단 하나의 클론(6913 생성 12931)과 클론 12931
백그라운드에서 실행되는 명령(예:
date&
)은 상위 쉘의 하위 쉘에서 실행되기 때문에 상위 쉘의 로컬 변수에 액세스할 수 있는 반면, 직접 실행되는 명령은(예:date
) 하위 쉘에서 실행되지 않기 때문에 액세스할 수 없습니다. 상위 쉘의 서브쉘. 추적된 출력을 사용하여 차이점을 설명할 수 있습니까?$ b=1 $ { echo $b; } & [1] 31214 1
이는
b
환경 변수가 아닌 상위 셸에 대한 로컬 변수입니다. 하위 셸은&
상위 셸의 복사본에서 생성되므로 상위 셸의 값을 미러링합니다. 나는 다음에서 이 예제를 만들었습니다.b
b
1
또 다른백그라운드 대신 명령 대체를 사용하며, 둘 다 명령을 실행하기 위한 하위 쉘을 생성합니다.