에서이것link exec bash 내장 명령에 대해 다음을 얻습니다.
명령이 제공되면쉘을 대체합니다새로운 프로세스를 만들지 않고.
쉘을 정확히 어떻게 대체합니까(즉, 내부적으로 어떻게 작동합니까)? exec*()
시스템 호출이 동일하게 작동 합니까 ?
답변1
예, 내장 기능은 궁극적으로 시스템 호출 계열 exec
중 하나를 사용합니다 . exec*()
정상적으로 명령을 실행하는 경우도 마찬가지입니다. 단지 를 사용할 때 새 프로세스를 생성하기 위해 먼저 시스템 호출을 exec
사용하지 않고 fork()
결과적으로 새 명령이 셸을 대체한다는 것입니다.
답변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
)이 부여되었는지 확인합니다 . 그런 다음 파일 이름이 가리키는 프로그램을 실행합니다. syscall 이후 프로세스를 제어할 수 있습니다. 그것은 무엇인가: . 또한 동일한 PID를 유지합니다. 종료 되면 프로세스도 종료됩니다. 더 이상 실행되지 않는지 여부입니다 ./bin/sleep
access()
execve()
execve()
sleep
nanosleep()
sleep
sleep
bash
증거:
다른 창에서 나는 ps
. 명령을 실행하기 전의 모습은 다음과 같았습니다.
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 -bash
그리고 실행하는 동안:
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 sleep 100
Afer는 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초 필요).