Отэтотссылка Я получаю следующее о встроенной команде 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
предоставлено ли разрешение на выполнение ( ) для /bin/sleep
системного access()
вызова. Затем execve()
выполняет программу, на которую указывает имя файла. После execve()
системного вызова sleep
имеет контроль над процессом. Делает свои вещи: nanosleep()
. Он также сохраняет тот же pid. После 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 секунд).