Deesselink, recebo o seguinte sobre o comando exec bash builtin:
Se o comando for fornecido, elesubstitui a cascasem criar um novo processo.
Como ele substitui exatamente o shell (ou seja, como funciona internamente)? A exec*()
chamada do sistema funciona da mesma forma?
Responder1
Sim, o exec
built-in, em última análise, faz uso de uma das exec*()
famílias de chamadas de sistema. O mesmo acontece com a execução de comandos normalmente. Acontece que quando você usa exec
, ele não usa a fork()
chamada do sistema primeiro para criar um novo processo, e o resultado é que o novo comando substitui o shell.
Responder2
Eu fiz uma instância strace
em execução bash
. Então invoquei o comando exec sleep 100
. Agora veja o que aconteceu:
access("/bin/sleep", X_OK) = 0
...
execve("/bin/sleep", ["sleep", "100"], [/* 14 vars */]) = 0
...
nanosleep({100, 0},
...
exit_group(0) = ?
Como você pode ver, aconteceu quase o mesmo que quando você liga sleep
da maneira normal. bash
verifica se a permissão executável ( X_OK
) é concedida /bin/sleep
com a access()
chamada do sistema. Em seguida, execve()
executa o programa apontado pelo nome do arquivo. Após execve()
o syscall, sleep
você tem o controle do processo. Será que são coisas: nanosleep()
. Ele também mantém o mesmo pid. Depois de sleep
finalizado o processo também termina. Se sleep
nem bash
não está mais em execução.
Evidência:
Em outra janela observei o processo com ps
. Antes de executar o comando estava assim:
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 -bash
E durante a execução:
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 sleep 100
Afer sleep
terminou o processo desapareceu.
O que aconteceu quando eu executei normalmente?
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) ---
A permissão de execução é verificada. Então um processo filho é criado clone()
. A bash
instância agora está no grupo de processos em segundo plano, sleep
no grupo de processos em primeiro plano. E por fim, a wait4()
chamada espera até que o processo filho termine (isso precisa de 100 segundos).