“서브 쉘”과“자식 프로세스”의 정확한 차이점은 무엇입니까?


16

이것이것 에 따르면 , 괄호를 사용하여 서브 쉘이 시작됩니다 (…).

( echo "Hello" )

이것 , 이것이것 에 따르면 , 명령이&

echo "Hello" &

Posix 스펙 은이 페이지 에서 단어 subshell 사용 하지만이를 정의하지 않으며 동일한 페이지에서 "자식 프로세스"를 정의하지 않습니다 .

둘 다 커널 fork()기능을 사용하고 있습니까?

그렇다면 어떤 포크를 "서브 쉘 (sub-shell)"이라고 부르는 것과 다른 포크를 "자식 프로세스 (child process)"라고 부르는 것의 정확한 차이점은 무엇입니까?


명확하지 왜 POSIX 연결하는 이론적 근거 : 기본 정의 대신의 기본 정의 자체 : 3.93 자식 프로세스 "주어진 프로세스에 의해 생성 된 새로운 프로세스 () (포크에 의해,의 posix_spawn (), 또는 ...)" ; 3.376 Subshell "주 또는 현재 쉘 실행 환경과 구별되는 쉘 실행 환경" . 따라서 같은 종류의 사례는 아닙니다. 찾고있는 구별입니까?
fra-san

@ fra-san A child processmain다음과 같이 다른 환경을 가질 수 있습니다 ( LANG=C eval 'echo "$LANG"' ). 그 자식 프로세스 (괄호 안에)도 서브 쉘 (다른 환경)입니까?
Isaac Isaac

의 표현 ( )입니다 정의 자체 실행 환경과 서브 쉘. 내 요점은 서브 쉘이 자식 프로세스로 구현 될 필요가 없다는 것입니다 (Stéphane이 ksh93 예제를 사용하여 답변에서 지적한 것처럼). 서브 쉘자식 프로세스모두fork() 호출의 결과 일 필요는없는 것 같습니다 . 따라서 두 종류의 포크의 차이점을 찾는 것이 올바른 견해가 아닙니다. 그래서 나는 당신의 질문을 더 잘 이해하려고 노력했습니다.
fra-san

아, 이제 당신이 링크 한 tldp 페이지가 실제로 서브 쉘 자식 프로세스 라고 말합니다 . 제 생각에는 정의가 오해의 소지가있는 단순화 일 수 있습니다.
fra-san

답변:


15

POSIX 용어에서 서브 쉘 환경은 Shell Execution Environment 개념과 연관되어 있습니다.

서브 쉘 환경은 상위 환경의 복제본으로 작성된 별도의 쉘 실행 환경입니다. 그 실행 환경에는 열린 파일, umask, 작업 디렉토리, 쉘 변수 / 함수 / 별칭 등이 있습니다.

해당 서브 쉘 환경에 대한 변경 사항은 상위 환경에 영향을 미치지 않습니다.

일반적으로 POSIX 스펙이 기반으로하는 Bourne 쉘 또는 ksh88에서 하위 프로세스를 포크하여 수행되었습니다.

POSIX가 서브 쉘 환경에서 명령 실행을 요구하거나 허용하는 영역은 전통적으로 ksh88이 자식 쉘 프로세스를 분기 한 영역입니다.

그러나 구현에서 하위 프로세스를 사용하도록 강요하지는 않습니다.

대신 쉘은 원하는 방식으로 별도의 실행 환경을 구현하도록 선택할 수 있습니다.

예를 들어, ksh93은 상위 실행 환경의 속성을 저장하고 포크를 피할 수있는 상황에서 서브 쉘 환경이 종료 될 때이를 복원함으로써이를 수행합니다 (대부분의 시스템에서 포크가 상당히 비싸기 때문에 최적화).

예를 들어,

cd /foo; pwd
(cd /bar; pwd)
pwd

POSIX는 cd /foo별도의 환경에서 실행하고 다음과 같이 출력해야합니다.

/foo
/bar
/foo

별도의 프로세스에서 실행할 필요가 없습니다. 예를 들어, stdout이 끊어진 파이프 pwd가되면 서브 쉘 환경에서 실행하면 SIGPIPE가 유일한 쉘 프로세스로 전송 될 수 있습니다.

를 포함한 대부분의 쉘 은 자식 프로세스에서 bash내부 코드를 평가하여 구현합니다 (...)(부모 프로세스는 종료를 기다리는 동안). 대신 ksh93은 코드를 내부 (...)에서 실행할 때 모두 동일한 프로세스로 수행합니다.

  • 서브 쉘 환경에 있다는 것을 기억하십시오.
  • cd이전 작업 디렉토리 (일반적으로 O_CLOEXEC로 열린 파일 디스크립터에)를 저장하고 OLDPWD, PWD 변수 및 cd수정 가능한 모든 값을 저장 한 후chdir("/bar")
  • 서브 쉘에서 돌아 오면 현재 작업 디렉토리 ( fchdir()저장된 fd에있는)와 서브 쉘이 수정 한 모든 것이 복원 됩니다.

자식 프로세스를 피할 수없는 컨텍스트가 있습니다. ksh93은 포크하지 않습니다 :

  • var=$(subshell)
  • (subshell)

그러나

  • { subshell; } &
  • { subshell; } | other command

즉, 작업이 별도의 프로세스에서 실행되어 동시에 실행될 수있는 경우입니다.

ksh93 최적화는 그 이상으로 진행됩니다. 예를 들어

var=$(pwd)

대부분의 쉘은 프로세스를 분기하고 자식 pwd이 stdout을 파이프로 리디렉션 하여 명령을 실행하고 pwd현재 작업 디렉토리를 해당 파이프에 쓰고 상위 프로세스가 파이프의 다른 쪽 끝에서 결과를 읽은 다음 ksh93두 가지 방법으로 가상화합니다. 포크와 파이프가 필요합니다. 포크와 파이프는 내장 명령이 아닌 경우에만 사용됩니다.

쉘이 하위 프로세스를 분기하는 서브 쉘 이외의 컨텍스트가 있습니다. 예를 들어, 별도의 실행 파일에 저장된 명령 (및 동일한 쉘 인터프리터 용 스크립트가 아님)을 실행하려면 셸에서 프로세스를 분기하여 명령을 실행해야합니다. 해당 명령이 반환 된 후 더 많은 명령을 실행할 수 있습니다.

에:

/bin/echo "$((n += 1))"

즉, 서브 쉘이 아니며, 현재 쉘 실행 환경에서 명령이 평가되고, 현재 쉘 실행 환경의 n변수가 증가하지만, 쉘은 인수로 /bin/echo확장 하여 해당 명령 을 실행하기 위해 하위 프로세스를 분기합니다. $((n += 1)).

많은 쉘은 스크립트 나 서브 쉘 (자식 프로세스로 구현 된 서브 쉘의 경우)의 마지막 명령 인 경우 외부 프로세스를 실행하기 위해 자식 프로세스를 포크하지 않는 최적화를 구현합니다. ( bash그러나 해당 명령이 서브 쉘의 유일한 명령 인 경우에만 수행됩니다).

즉, 해당 셸에서 하위 셸의 마지막 명령이 외부 명령 인 경우 하위 셸은 추가 프로세스를 생성하지 않습니다. 당신이 비교하면 :

a=1; /bin/echo "$a"; a=2; /bin/echo "$a"

a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")

두 번째 경우에만 동일한 수의 프로세스가 작성되며 두 번째 포크는 a=2서브 쉘 환경에서 실행 되도록 더 일찍 수행 됩니다.


1

서브 쉘

자식 셸은 하위 셸이라고도합니다. 서브 쉘은 상위 쉘과 다른 쉘에서 작성할 수 있습니다. 다음을 사용하여 서브 쉘을 작성할 수 있습니다.

1. 프로세스 목록

프로세스 목록은 괄호로 묶인 명령 그룹입니다. 예:

( pwd ; (echo $BASH_SUBSHELL)) 

현재 작업 디렉토리와 스폰 된 쉘 수를 인쇄합니다. 참고 서브 쉘 호출은 비용이 많이 듭니다.

2. 코 프로세스

백그라운드 모드에서 서브 쉘을 생성하고 해당 서브 쉘 내에서 명령을 실행합니다.

coproc sleep 10

jobscommand 를 입력하면

[1]+  Running                 coproc COPROC sleep 10 &

백그라운드에서 실행중인 백그라운드 프로세스로 절전 모드가 표시됩니다.

자식 프로세스를 포크

컴퓨팅의 자식 프로세스는 다른 프로세스에서 만든 프로세스입니다. 외부 명령이 실행될 때마다 하위 프로세스가 작성됩니다. 이 동작을 포크라고합니다.

$ps -f
UID        PID  PPID  C STIME TTY          TIME CMD  
umcr7     3647  3638  0 13:54 pts/0    00:00:00 bash
umcr7     3749  3647  0 13:59 pts/0    00:00:00 ps -f

ps -f외부 명령과 마찬가지로 (즉, 파일 시스템 명령이라고도하는 외부 명령은 bash 셸 외부에 존재하는 프로그램입니다.)이 명령을 실행하면 bash 셸의 부모 ID로 자식 프로세스가 만들어집니다.


0

서브 쉘과 하위 쉘 모두 상위 쉘과 별개의 프로세스입니다 (모두 쉘의 하위). 즉, 다른 PID가 있습니다. 그리고 둘 다 부모 쉘의 포크 (복사)로 시작합니다.

서브 쉘은 변수, 함수, 플래그 및 모든 것을 상위 쉘에서와 같이 사용할 수있는 상위 쉘의 사본입니다. 그러한 값의 수정은 부모에게 영향을 미치지 않습니다.

자식 셸은 포크로 시작하지만 시작 구성에서 제공하는 셸 기본값으로 다시 설정됩니다. 일부 코드 (쉘 또는 명령)를 실행하는 데 사용되는 프로세스가됩니다.

서브 쉘은 변수 값에 액세스 할 수 있습니다.

$ x=123; ( echo "$x")
123

자식 셸에서 내 보낸 변수를 내보낼 수 없습니다.

$ x=234; sh -c 'echo "x=$x"'
x=
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.