Primeiro, um pouco da terminologia .
Um executável é um arquivo simples no seu sistema. Um processo é o nutshell que executa o programa incorporado em um arquivo executável.
Você está certo sobre o modo em que um arquivo executável é iniciado :
- O processo pai (já existente)
fork
s em si, levando em dois fluxos de execução desse ponto. Um vivendo no processo pai e outro vivendo em um novo processo. - O novo processo (filho) se silencia para executar o programa do executável a ser executado. Isso é feito usando um syscall do
exec
família.
Tomando o exemplo de uma interface gráfica na qual você clica duas vezes em um ícone executável, você tem seu executável bifurcado a partir do processo que mostra o ícone em que você clicou basicamente com este código-fonte:
const char *exe_path = taken_from_icon();
int pid = fork();
if(pid == 0)
{
// I am the new child
execl(exe_path, exe_path, NULL);
// exec only return in case of failure
exit(EXIT_FAILURE);
}
// I am the graphical interface,
// Continue and wait for another clic
Mas a morte e pais da criança não é exatamente como você diz.
Basicamente - e quando o processo pai ainda está ativo - o processo filho é o filho de seu pai (sim! -) Ele tem seu PPID (ID do processo pai) configurado para o processo ainda vivo que o bifurcou.
As coisas mudam quando o processo pai é interrompido. O processo filho continua a funcionar, mas seu PPID está configurado para um processo pai ativo ainda ativo. Há sempre uma vez que o processo init
nunca morre.
O fato de as crianças shell morrerem quando a própria casca morre é algo específico. Eu vejo duas razões para isso:
-
O primeiro: um shell geralmente mantém uma lista de PIDs que ele bifurcou. E quando a concha morre, ela mata todos eles. Os principais shells têm um comando interno
disown
para remover um filho dessa lista e deixá-lo vivo quando o shell morre. Veja a página man do bash :The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the signal to a particular job, it should be removed from the jobs table with the disown builtin (see SHELL BUILTIN COMMANDS below) or marked to not receive SIGHUP using disown -h.
-
O segundo: os filhos de shell geralmente têm stdin, stdout e stderr conectados à própria shell por meio de pipes. Se o shell parar de consumir stdout filho (geralmente para imprimí-lo) ou fechar o final do seu pipe, o filho poderá ter falhas ao gravar em seu stdout, o que pode bloquear ou eliminá-lo.