Como o exec bash trabalha internamente?

5

De este link eu recebo o seguinte sobre exec bash builtin comando:

If command is supplied, it replaces the shell without creating a new process.

Como exatamente substitui o shell (ou seja, como funciona internamente)? A chamada do sistema exec*() funciona da mesma maneira?

    
por syntagma 10.10.2014 / 19:25

2 respostas

8

Sim, o exec builtin faz uso de uma das famílias exec*() de chamadas do sistema. Funciona também com comandos normalmente. É só que quando você usa exec , ele não usa a chamada do sistema fork() primeiro para criar um novo processo, e o resultado é que o novo comando substitui o shell.

    
por 10.10.2014 / 19:38
7

Eu fiz um strace em uma instância bash em execução. 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)                           = ?

Então, você pode ver, aconteceu quase como quando você chama sleep do modo normal. bash verifica se a permissão executável ( X_OK ) é concedida para /bin/sleep com a chamada do sistema access() . Então execve() executa o programa apontado pelo nome do arquivo. Depois de execve() syscall, sleep tem o controle sobre o processo. Faz as coisas: nanosleep() . Ele também mostra o mesmo pid. Depois que sleep terminou, o processo termina também. Se sleep nem bash não está mais sendo executado.

Evidências:

Em outra janela, assisti ao processo com ps . Antes de executar o comando, ficou assim:

$ ps -o stat,pid,cmd -p <pid>
Ss+  10905 -bash

E enquanto corre:

$ ps -o stat,pid,cmd -p <pid>
Ss+  10905 sleep 100

Afer sleep terminou o processo desapareceu.

O que aconteceu quando eu corri 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 está marcada. Em seguida, um processo filho é criado clone() . A instância bash está agora no grupo de processos em segundo plano, sleep está no grupo de processos em primeiro plano. E, por fim, a chamada wait4() aguarda até que o processo filho seja finalizado (que precisa de 100 segundos).

    
por 10.10.2014 / 20:14

Tags