Por que o fork do mecanismo de criação de processo padrão?

40

A chamada do sistema UNIX para criação de processo, fork (), cria um processo filho copiando o processo pai. Meu entendimento é que isso é quase sempre seguido por uma chamada para exec () para substituir o espaço de memória do processo filho (incluindo o segmento de texto). Copiar o espaço de memória do pai em fork () sempre me pareceu um desperdício (embora eu tenha percebido que o desperdício pode ser minimizado fazendo com que os segmentos de memória copiem e escrevam de forma que apenas os ponteiros sejam copiados). De qualquer forma, alguém sabe por que essa abordagem de duplicação é necessária para a criação do processo?

    
por Ellen Spertus 07.02.2012 / 20:13

2 respostas

50

É simplificar a interface. A alternativa para fork e exec seria algo como o Windows ' função CreateProcess . Observe quantos parâmetros CreateProcess tem e muitos deles são estruturas com ainda mais parâmetros. Isso porque tudo que você deseja controlar sobre o novo processo deve ser passado para CreateProcess . Na verdade, CreateProcess não tem parâmetros suficientes, então a Microsoft precisou adicionar CreateProcessAsUser e CreateProcessWithLogonW .

Com o modelo fork/exec , você não precisa de todos esses parâmetros. Em vez disso, determinados atributos do processo são preservados em exec . Isso permite que você use fork e, em seguida, altere os atributos de processo desejados (usando as mesmas funções que você usaria normalmente) e , em seguida, exec . No Linux, fork não possui parâmetros e execve tem apenas 3: o programa a ser executado, a linha de comando para fornecê-lo e seu ambiente. (Há outras funções exec , mas elas são apenas wrappers em torno de execve fornecidas pela biblioteca C para simplificar os casos de uso comuns.)

Se você quiser iniciar um processo com um diretório atual diferente: fork , chdir , exec .

Se você quiser redirecionar stdin / stdout: fork , feche / abra arquivos, exec .

Se você quiser trocar de usuário: fork , setuid , exec .

Todas essas coisas podem ser combinadas conforme necessário. Se alguém apresentar um novo tipo de atributo de processo, você não precisará alterar fork e exec .

Como larsks mencionou, a maioria dos Unixes modernos usa copy-on-write, portanto fork não envolve sobrecarga significativa.

    
por 07.02.2012 / 20:31
5

Além da resposta do cjm, a única especificação Unix define uma função chamada vfork() . Essa função funciona como fork, exceto que o processo bifurcado tem um comportamento indefinido se ele faz algo diferente de tentar chamar uma função familly exec ou chamar _exit() .

Assim, praticamente o único uso com comportamento definido é:

pid_t ret = vfork();
if(ret == 0)
{
    exec(...);
    _exit(EXIT_FAILURE); //in case exec failed for any reason.
}

Então, o que vfork faz? É um fork barato. Em implementações sem copy-on-write, o processo resultante compartilhará espaço de memória com o processo original (daí o comportamento indefinido). Em implementações com copy-on-write, vfork tem permissão para ser idêntico a fork() , já que as implementações de copy-on-write são rápidas.

Existe também a função opcional posix_spawn (e uma função posix_spawnp ) que pode criar diretamente um novo processo. (Também é permitido implementá-las com uma chamada de biblioteca usando fork e exec , e um exemplo de implementação é fornecido.)

    
por 07.02.2012 / 22:09