[Vou repetir parte da minha resposta daqui .]
Por que não apenas ter um comando que cria um novo processo do zero? Não é absurdo e ineficiente copiar um que só será substituído imediatamente?
De fato, isso provavelmente não seria tão eficiente por alguns motivos:
A "cópia", produzido por fork()
um pouco de uma abstração, uma vez que o kernel usa um copy-on-write sistema ; tudo o que realmente precisa ser criado é um mapa de memória virtual. Se a cópia ligar imediatamente exec()
, a maioria dos dados que teriam sido copiados se tivessem sido modificados pela atividade do processo nunca precisará realmente ser copiada / criada porque o processo não faz nada que exija seu uso.
Vários aspectos significativos do processo filho (por exemplo, seu ambiente) não precisam ser duplicados ou configurados individualmente com base em uma análise complexa do contexto etc. Eles assumem que eles são os mesmos do processo de chamada e este é o sistema bastante intuitivo com o qual estamos familiarizados.
Para explicar # 1 um pouco mais, a memória que é "copiada", mas nunca acessada posteriormente nunca é realmente copiada, pelo menos na maioria dos casos. Uma exceção nesse contexto pode ser se você bifurcar um processo e depois encerrar o processo pai antes que o filho se substitua exec()
. Eu digo poder porque muito do pai poderia ser armazenada em cache se não houver memória livre suficiente, e eu não tenho certeza até que ponto isso seria explorado (que dependem da implementação OS).
Obviamente, isso não torna a cópia mais eficiente do que usar uma folha em branco - exceto "a folha em branco" não é literalmente nada e deve envolver alocação. O sistema pode ter um modelo de processo em branco / novo genérico que copie da mesma maneira, 1 mas que, na verdade, não salvaria nada em comparação com o fork de copiar na gravação. Portanto, o nº 1 apenas demonstra que o uso de um "novo" processo vazio não seria mais eficiente.
O ponto 2 explica por que o uso do garfo é provavelmente mais eficiente. O ambiente de uma criança é herdado de seu pai, mesmo que seja um executável completamente diferente. Por exemplo, se o processo pai for um shell, e o filho, um navegador da web, $HOME
ainda for o mesmo para os dois, mas como qualquer um deles poderá alterá-lo posteriormente, elas deverão ser duas cópias separadas. O da criança é produzido pelo original fork()
.
1. Uma estratégia que pode não fazer muito sentido literal, mas o que quero dizer é que criar um processo envolve mais do que copiar sua imagem na memória do disco.