O que acontece quando digitamos um comando simples no shell? [duplicado]

31
    

Esta pergunta já tem uma resposta aqui:

    

Eu tenho uma pergunta simples sobre a execução de um comando simples. Pelo que entendi, quando digitamos um comando como ls em um shell interativo,

  1. O Shell interpreta o comando.
  2. O Shell cria um processo filho e executa o comando no processo filho.
  3. O Shell aguarda a conclusão do processo filho.

Se meu entendimento estiver correto, um comando simples que digitamos no prompt do shell é executado em um processo filho e o resultado do comando não afeta o ambiente atual do shell.

Se sim, e os comandos incorporados como cd ? Se cd for executado em um processo filho e não puder afetar o ambiente atual do shell, como o diretório de trabalho do shell atual pode ser alterado?

    
por MS.Kim 07.04.2014 / 04:32

2 respostas

31

O shell é apenas um programa, embora desempenhe um papel importante no sistema. Bash, e eu diria que a maioria dos outros shells comuns, são implementados em C. As duas mais importantes chamadas de sistema nativas que são usados na criação de subprocessos são fork() e exec() . Essas funções geralmente são implementadas em linguagens de nível superior, incluindo o shell.

  1. fork()

    "Fork" cria uma cópia duplicada do processo de chamada como seu filho. É assim que virtualmente todos os processos no sistema, exceto o primeiro ( init ) começam: como cópias do processo que começou eles. A linguagem da shell não tem, na verdade, uma função fork , mas inclui a sintaxe para gerar subshells, que são a mesma coisa.

  2. exec()

    Não existe realmente uma chamada exec() em C, mas refere-se coloquialmente a um grupo de funções relacionadas; você pode ver a lista com man 3 exec , que geralmente começa:

    The exec() family of functions replace the current process image with a new process image...

    E é exatamente isso que faz: substitui a definição de partes da pilha de memória do processo atual com material novo carregado de um arquivo executável (por exemplo, /usr/bin/ls ). É por isso que fork() é necessário primeiro na criação de um novo processo - caso contrário, o processo de chamada deixa de ser o que era e se transforma em outra coisa; nenhum novo processo seria realmente criado.

A princípio, pode parecer uma maneira absurda e ineficiente de fazer as coisas: por que não apenas ter um comando que crie um novo processo do zero? Na verdade, isso provavelmente não seria tão eficiente por alguns motivos:

  • A "cópia" produzida por fork() é um pouco de abstração, já que o kernel usa um copy-on - escreva o sistema ; tudo o que realmente precisa ser criado é um mapa de memória virtual. Se a cópia chamar imediatamente exec() , a maioria dos dados que teriam sido copiados se tivessem sido modificados pela atividade do processo nunca terão que ser copiados / criados 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 individualmente duplicados ou definidos com base em uma análise complexa do contexto, etc. Eles são apenas considerados como sendo os mesmos do processo de chamada, e este é o sistema razoavelmente intuitivo com o qual estamos familiarizados.

Para uma discussão detalhada de exatamente o que significa "copiar o ambiente" para o processo filho gerado, consulte minha resposta aqui .

If so, what about built-in commands like cd?

Elas são, novamente, implementadas apenas em C. chdir() , como fork() e exec() , faz parte das extensões da plataforma Unix para o padrão C e do que é subjacente ao comando cd do shell. De man 2 chdir :

chdir() changes the current working directory of the calling process to the directory specified in path.

Isso não requer um subprocesso - afeta o chamador. O shell é um interpretador de tempo de execução interativo , o que significa que ele executa o código escrito na linguagem shell conforme você o alimenta. . Na maioria das vezes não precisa executar um novo processo para fazer isso, ele faz isso sozinho.

    
por 07.04.2014 / 05:14
8

If so, what about built-in commands like cd? If cd is executed on a child process

Aqui está a falha em sua lógica. cd , sendo um shell embutido, é interpretado especialmente pelo shell e "executado" no processo. Você pode usar o comando type para descobrir se um comando está embutido ou não.

    
por 07.04.2014 / 04:59