Como o exec bash integrado funciona internamente?

Como o exec bash integrado funciona internamente?

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 execbuilt-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 straceem 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 sleepda maneira normal. bashverifica se a permissão executável ( X_OK) é concedida /bin/sleepcom a access()chamada do sistema. Em seguida, execve()executa o programa apontado pelo nome do arquivo. Após execve()o syscall, sleepvocê tem o controle do processo. Será que são coisas: nanosleep(). Ele também mantém o mesmo pid. Depois de sleepfinalizado o processo também termina. Se sleepnem bashnã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 sleepterminou 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 bashinstância agora está no grupo de processos em segundo plano, sleepno grupo de processos em primeiro plano. E por fim, a wait4()chamada espera até que o processo filho termine (isso precisa de 100 segundos).

informação relacionada