No POSIX, os processos são “relacionados” entre si por meio de duas hierarquias básicas:
A hierarquia dos processos pai e filho.
A hierarquia de sessões e grupos de processos.
Os processos do usuário têm muito controle sobre o último, via setpgid
e setsid
, mas eles têm muito pouco controle sobre o primeiro—o ID do processo pai é definido quando um processo é gerado e alterado pelo kernel quando o pai sai (geralmente para PID 1 ), mas caso contrário não muda. Refletindo sobre isso, tenho me perguntado quão importante é o relacionamento entre pais e filhos.
Aqui está um resumo do meu entendimento até agora:
Os relacionamentos pai-filho são claramente importantes do ponto de vista do processo pai , pois várias syscalls, como
wait
esetpgid
, são permitidas apenas em processos filho.A relação sessão-grupo-processo é claramente importante para todos os processos, tanto para o líder da sessão quanto para outros processos na sessão, uma vez que syscalls
kill
operam em grupos de processos inteiros,setpgid
só podem ser usados para ingressar em um grupo na mesma sessão e todos os processos no grupo de processos em primeiro plano de uma sessão são enviadosSIGHUP
se o líder da sessão sair.Além disso, as duas hierarquias estão claramente relacionadas do ponto de vista do pai, uma vez que
setsid
afeta apenas novos filhos esetpgid
só podem ser usadas em crianças, mas parecem essencialmente não relacionadas do ponto de vista da criança (uma vez que o processo de morte do pai não tem impacto algum no grupo ou sessão de um processo).
No entanto, visivelmente ausente está qualquer razão para um processo filho se importar com o que seu pai atual é. Portanto, tenho a seguinte pergunta: o valor atual de getppid()
tem alguma importância do ponto de vista do processo filho , além de talvez identificar se seu processo de desova saiu ou não?
Para colocar a mesma questão de outra forma, imagine que o mesmo programa é gerado duas vezes, do mesmo pai, de duas maneiras diferentes:
O primeiro filho é gerado da maneira usual,
fork()
seguido porexec()
.O segundo filho é gerado indiretamente: o processo pai chama
fork()
, e o filho também chamafork()
, e é o processo neto que chamaexec()
. O filho imediato sai, então o neto fica órfão e seu PPID é reatribuído ao PID 1.
Nesse cenário hipotético, supondo que tudo o mais seja igual, algum programa razoável tem algum motivo para se comportar de maneira diferente? Até agora, minha conclusão parece ser “não”, já que a sessão permanece inalterada, assim como os descritores de arquivos herdados do processo… mas não tenho certeza.
Nota: Eu não considero “adquirir o PID pai para se comunicar com ele” como uma resposta válida para essa pergunta, uma vez que programas órfãos geralmente não podem confiar que seu PPID seja definido como 1 (alguns sistemas definem o PPID de processos órfãos para alguns outro valor), portanto, a única maneira de evitar uma condição de corrida é adquirir o ID do processo pai por meio de uma chamada para getpid()
antes da bifurcação e, em seguida, usar esse valor no filho.