Como funcionam o fork e o exec?

17

Não tenho muita experiência, apenas tentando me envolver nos processos, como eles interpretam o hardware no nível do usuário.

Portanto, quando um comando é acionado a partir de um shell, fork()herda um processo filho e exec()carrega o processo filho na memória e é executado.

  1. Se o processo filho contiver todos os atributos do processo pai (que é o processo original), qual é a necessidade desse processo filho? O processo original também pode ter sido carregado na memória.
  2. Isso forke execconceito se aplicam a todo o programa executável no UNIX? Como para o shell script também ou apenas para comandos? Também se aplica a comandos internos do shell?
  3. Quando a cópia na gravação é usada se eu executar um comando / script?

Desculpe por fazer muitas perguntas ao mesmo tempo, mas todas essas perguntas vêm à minha mente ao pensar em qualquer execução de comando.

PriB
fonte
Não direi que isso é uma duplicata, mas acho que algumas das suas perguntas foram respondidas aqui: unix.stackexchange.com/questions/136637/… e na outra resposta vinculada na parte superior dessa.
21915 goldilocks

Respostas:

22

Portanto, quando um comando é acionado a partir de um shell, o fork () herda um processo filho e o exec () carrega o processo filho na memória e é executado.

Não é bem assim. fork()clona o processo atual, criando um filho idêntico. exec()carrega um novo programa no processo atual, substituindo o existente.

Meu qs é:

Se o processo filho contiver todos os atributos do processo pai (que é o processo original), qual é a necessidade desse processo filho? O processo original também pode ter sido carregado na memória.

A necessidade é porque o processo pai ainda não deseja finalizar; ele quer que um novo processo seja executado e faça algo ao mesmo tempo em que continua sendo executado.

Esse conceito de fork e exec se aplica a todo o programa executável no UNIX, como também para scripts de shell ou apenas para comandos? Também se aplica a comandos internos do shell?

Para comandos externos, o shell faz fork()isso para que o comando seja executado em um novo processo. Builtins são apenas executados diretamente pelo shell. Outro comando notável é o execque informa o shell ao exec()programa externo sem primeiro fork(). Isso significa que o próprio shell é substituído pelo novo programa e, portanto, não está mais lá para que o programa retorne quando sair. Se você diz, exec truee depois /bin/trueirá substituir o seu shell, e imediatamente saída, não deixando nada em execução no seu terminal mais, então ele será fechado.

quando copiar no conceito de gravação é usado se eu executar um comando / script?

Na era da pedra, fork()na verdade , era necessário copiar toda a memória do processo de chamada para o novo processo. Copy on Write é uma otimização em que as tabelas de páginas são configuradas para que os dois processos comecem a compartilhar toda a mesma memória e apenas as páginas que são gravadas por qualquer processo são copiadas quando necessário.

psusi
fonte
4
"Para quase todos os comandos, o shell executa um fork () para que o comando seja executado em um novo processo. Se esse comando for interno, o filho não precisará executar um programa separado." Boa resposta, mas esta parte deve ser editada. O shell não bifurca ao executar os embutidos. Ele executa aqueles diretamente no processo de shell ativo. Essa é a única maneira que os componentes internos gostam cdou readpodem funcionar. A falta de bifurcação também torna os componentes internos muito mais rápidos que os comandos externos.
John Kugelman apoia Monica
6
  1. Para alguns programas, o processo filho faz uma coisa (ler de uma porta serial, gravar no terminal) e o processo pai continua a fazer outra coisa (ler do terminal, gravar na porta serial). Outro exemplo clássico é que o processo filho faz um ponto de verificação de qualquer cálculo de execução demorada. Principalmente, o processo filho faz algumas configurações, como alterar o diretório, redefinir os manipuladores de sinal ou redefinir os descritores de arquivo e depois chama execve()para se sobrepor a um código diferente.
  2. fork()e se exec()aplicam a todos os executáveis ​​- de fato, junto com argc e argv, e pipes, fork e exec são o que diferenciam o Unix de outros sistemas operacionais. fork()Existem algumas especializações ou generalizações de existem, como BSD vfork(), Plan 9 rfork()e Linux ' clone(), mas o principal permanece o mesmo.
  3. "copiar na gravação" não aparece realmente para o usuário, é mais uma técnica para otimizar a criação de um processo filho e durante sua execução. A pilha de chamadas e a pilha (memória alocada com malloc(), ou mesmo variáveis ​​de escopo estáticas ou globais) podem ser "cópia na gravação". Quando um processo filho é criado com umfork()Na chamada, o kernel configuraria o processo filho para ter exatamente as mesmas páginas de memória que a pilha e a pilha que o processo pai. Se o hardware (unidade de gerenciamento de memória) detectar uma gravação do heap ou da pilha, o kernel obterá uma nova página física de memória, copiará a página do pai na nova página e mapeará essa nova página na pilha ou pilha do processo filho. Isso constitui uma otimização, pois o kernel gasta menos tempo configurando mapeamentos de página do que faria para copiar a pilha e o heap completamente para o processo filho.
Bruce Ediger
fonte
Obrigado Bruce pela sua resposta. Mas tantas coisas que você disse aqui que estão passando pela minha cabeça. Não tenho muito conhecimento dessas coisas ... tentarei fazer com que essas funções funcionem, como você mencionou. Muito obrigado..!!
PriB
4
Se o processo filho contiver todos os atributos do processo pai (que é o processo original), qual é a necessidade desse processo filho? O processo original também pode ter sido carregado na memória.

Esta pergunta é respondida de maneira ilustrativa, examinando as implementações mais antigas do Unix, que tinham que funcionar sob severas restrições de memória e tinham apenas um processo de execução no espaço de memória / endereço por vez.

A multitarefa foi obtida trocando um processo para disco e trocando um processo diferente.

Agora, a forkchamada do sistema era quase a mesma: ela trocou um processo para o disco, mas, em vez de trocar outro processo, deu à cópia na memória outro ID de processo e retornou a ele. E esse foi um momento oportuno para esse processo decidir apenas execpara outro executável, afinal.

fork+ execportanto, na verdade, não ocorreu uma sobrecarga perceptível sobre a desova: você tinha que trocar seu processo para o disco de qualquer maneira e tinha a imagem antiga do processo em locais de memória viáveis.

Com quantidades crescentes de unidades de gerenciamento de memória e memória disponíveis e vários processos na memória, o custo inicialmente insignificante de um garfo se tornou um incômodo para algumas arquiteturas: assim vforknasceu.

user99727
fonte
2

Para tornar isso o mais fácil de entender possível, usarei uma analogia. Vamos assar uma torta!

Pegamos o livro de receitas e começamos a ler e a preparar uma torta de ruibarbo com morango (a minha favorita), com uma crosta feita à mão. Quase tudo o que precisamos está na cozinha, exceto os ovos e as frutas, mas como vivemos em uma fazenda e as frutas estão na estação, isso não é um problema. o problema é que o forno está quebrado e não há tempo suficiente para fazer tudo. Não seria bom ter mais de um de mim?

fork () para o resgate. Agora há dois de mim. e nós dois vamos para a cozinha para começar a fazer a massa de torta. oops. Então, olhamos para o retorno do fork. Eu tenho um grande número que ele tem zero, então vou para a cozinha enquanto ele se dirige para o galinheiro e o jardim. Quando passo pelo forno, bifurco () novamente, observe o valor de retorno: que chatice, fiquei zero. Ele continua com a farinha enquanto eu encaro o forno quebrado. Abro a porta, sem luz, fecho a porta. Alguém sabe como consertar um forno?

exec () para o resgate. Pego o voltímetro no cinto de ferramentas, a lâmpada pode ser diagnóstica, então verifico a potência. enquanto caminho até o painel do disjuntor, vejo um colega colhendo ruibarbo. Que nojo! Eu prefiro torta de chocolate com seda.

hildred
fonte