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
서브 쉘 환경에서 실행 되도록 더 일찍 수행 됩니다.