~에서이것링크 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
)을 부여하는지 확인합니다. 그런 다음 파일 이름이 가리키는 프로그램을 실행하십시오. 시스템 호출 후에는 프로세스를 제어할 수 있습니다. 그 것 :. 또한 동일한 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
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초 소요).