Os processos são executados a partir do Bash executado em um “sub shell”?

1

Quando executo um executável (como a.out) a partir de um shell Bash, esse executável é executado em algum tipo de shell "sub", ou seja, diferente do shell no qual estou digitando?

Vou tentar ilustrar minha pergunta com um exemplo. O programa a seguir obtém e imprime o valor de uma variável de ambiente, altera-a, recobre e imprime novamente:

#include <iostream>
#include <string>
#include <cstdlib>
int main( int argc, char* argv[] )
{
  std::string str( getenv( "FOO" ) );
  std::cout << str << std::endl;
  setenv( "FOO", "bar", 1 );
  str = getenv( "FOO" );
  std::cout << str << std::endl;
  return 0;
}

Agora, observe a saída quando eu executar o seguinte no meu prompt do Bash:

>unset FOO && export FOO=foo && printf "$FOO\n" && ./a.out && printf "$FOO\n"
foo
foo
bar
foo
>
>unset FOO && export FOO=baz && printf "$FOO\n" && ./a.out && printf "$FOO\n"
baz
baz
bar
baz

Por isso, estou exportando FOO para que seja possível extrair do executável - eu entendo isso. E a saída do executável mostra que o envvar está sendo alterado.

Mas a% final printf "$FOO\n" imprime o valor pré-executável. Isso ocorre porque o executável é executado em um "ambiente diferente" do que onde eu digito comandos?

    
por StoneThrow 24.02.2018 / 01:08

1 resposta

3

No Unix, cada processo tem sua própria cópia independente do ambiente. Um processo obtém seu ambiente inicial quando é criado (via fork() ) copiando o ambiente do processo pai.

Portanto, se você adicionar uma variável ao ambiente do shell antes de chamar a.out, a.out a verá (porque a.out recebeu uma cópia do ambiente do shell, que continha aquela variável).

Se a.out muda o ambiente, isso muda o ambiente de a.out - não o da shell. Se a.out fosse chamar outro programa (por exemplo, usando system() ), esse programa veria o ambiente alterado, porque ele obteria uma cópia do ambiente de a.out.

Quando a.out sai, suas variáveis de ambiente são destruídas; é claro que, se um processo filho estivesse em execução, ele ainda manteria sua cópia (até sair).

Se você modificar o ambiente no shell, enquanto a.out ainda estiver em execução (por exemplo, em segundo plano: a.out & ), então a.out não verá as alterações: o ambiente é copiado apenas na criação do processo.

[Note que este é o caminho típico; o execve syscall permite que você execute um programa com um ambiente que você especifica, em vez do que foi copiado do processo pai.]

    
por 24.02.2018 / 02:20