프로세스는 "하위 쉘"에서 실행되는 Bash에서 실행됩니까?

프로세스는 "하위 쉘"에서 실행되는 Bash에서 실행됩니까?

Bash 셸에서 실행 파일(예: a.out)을 실행할 때 실행 파일이 일종의 "하위" 셸에서 실행되고 있습니까? 즉, 입력 중인 셸과 다른가요?

예를 들어 내 문제를 설명하려고 노력할 것입니다. 다음 프로그램은 환경 변수의 값을 가져와서 인쇄하고, 변경한 후 다시 가져와서 인쇄합니다.

#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;
}

이제 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

FOO그래서 실행 파일에서 가져올 수 있도록 내보내는 중입니다 . 이해합니다. 실행 파일의 출력에는 환경 변수가 변경되고 있음이 표시됩니다.

그러나 결국 printf "$FOO\n"사전 실행 값이 인쇄됩니다. 실행 파일이 명령을 입력한 위치와 "다른 환경"에서 실행되고 있기 때문입니까?

답변1

유닉스에서는 각각프로세스환경에 대한 독립적인 복사본을 갖습니다. 프로세스는 fork()상위 프로세스의 환경을 복사하여 생성될 때 초기 환경을 얻습니다.

따라서 a.out을 호출하기 전에 쉘 환경에 변수를 추가하면 a.out이 이를 보게 됩니다(a.out이 변수를 포함하는 쉘 환경의 사본을 수신하기 때문입니다).

a.out이 환경을 변경하면 쉘 환경이 아닌 a.out의 환경이 변경됩니다. a.out이 다른 프로그램을 호출하는 경우(예: 를 사용하여 system()) 해당 프로그램은 a.out 환경의 복사본을 가져오기 때문에 변경된 환경을 보게 됩니다.

a.out이 종료되면 해당 환경 변수는 삭제됩니다. 물론 하위 프로세스가 실행 중인 경우 해당 프로세스의 복사본은 종료될 때까지 유지됩니다.

a.out이 계속 실행되는 동안(예: 백그라운드에서) 셸에서 환경을 수정하면 a.out &a.out에는 변경 사항이 표시되지 않습니다. 환경은 프로세스가 생성될 때만 복사됩니다.

[이것은 일반적입니다. 시스템 execve호출을 사용하면 상위 프로세스에서 복사한 환경이 아닌 지정된 환경을 사용하여 프로그램을 실행할 수 있습니다. ]

관련 정보