
~에 따르면이것그리고이것, 서브쉘은 괄호를 사용하여 시작됩니다 (…)
.
( echo "Hello" )
~에 따르면이것,이것그리고이것, 명령이 다음으로 끝날 때 프로세스가 분기됩니다.&
echo "Hello" &
Posix 사양의 사용법subshell
이 페이지의 단어하지만 정의하지 않고 같은 페이지에서"하위 프로세스"가 정의되지 않았습니다.
둘 다 커널 fork()
기능을 사용합니다. 그렇죠?
일부 포크를 "서브쉘"이라고 부르는 것과 다른 포크를 "하위 프로세스"라고 부르는 것의 정확한 차이점은 무엇입니까?
답변1
POSIX 용어에서 서브셸 환경은 다음 개념과 연관됩니다.쉘 실행 환경.
서브셸 환경은 상위 환경의 복사본으로 생성된 별도의 셸 실행 환경입니다. 실행 환경에는 열린 파일, umask, 작업 디렉터리, 셸 변수/함수/별칭 등이 포함됩니다.
하위 셸 환경을 변경해도 상위 환경에는 영향을 주지 않습니다.
전통적으로 POSIX 사양의 기반이 되는 Bourne 셸 또는 ksh88에서는 하위 프로세스를 포크하여 이 작업을 수행합니다.
POSIX가 서브셸 환경에서 명령을 실행하도록 요구하거나 허용하는 영역은 기존 ksh88이 서브셸 프로세스를 생성하는 영역입니다.
그러나 구현에서 이 목적을 위해 하위 프로세스를 사용하도록 강제하지는 않습니다.
쉘은 원하는 방식으로 이 별도의 실행 환경을 구현하도록 선택할 수 있습니다.
예를 들어 ksh93은 상위 실행 환경의 속성을 저장하고 분기를 피할 수 있는 컨텍스트에서 하위 셸 환경이 종료될 때 이를 복원하여 이를 구현합니다(대부분의 시스템에서 분기는 상당히 비용이 많이 들기 때문에 최적화).
예를 들어:
cd /foo; pwd
(cd /bar; pwd)
pwd
cd /bar
POSIX는 별도의 환경에서 실행 해야 하며 다음과 같이 출력됩니다.
/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))
.
shell -c 'inline-script'
많은 쉘은 외부 명령이 인라인 스크립트( ) 또는 서브쉘(하위 프로세스로 구현된 서브쉘의 경우)의 마지막 명령인 경우 외부 명령을 실행하기 위해 하위 프로세스를 생성하지 않는 최적화를 구현합니다. ( bash
그러나 이는 해당 명령이 서브쉘의 유일한 명령인 경우에만 수행됩니다).
이는 이러한 셸의 경우 하위 셸의 마지막 명령이 외부 명령인 경우 하위 셸이 추가 프로세스를 생성하지 않는다는 것을 의미합니다. 비교한다면:
a=1; /bin/echo "$a"; a=2; /bin/echo "$a"
그리고
a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")
동일한 수의 프로세스가 생성되며, 두 번째 경우에만 두 번째 포크가 일찍 완료되어 a=2
서브셸 환경에서 실행됩니다.
답변2
둘 다(서브쉘과 서브쉘)은 상위 쉘(둘 다 상위 쉘의 하위 쉘)과 별개의 프로세스입니다. 즉, 서로 다른 PID를 가지고 있습니다. 둘 다 상위 쉘의 분기(사본)로 시작합니다.
서브셸은 상위 셸에서와 마찬가지로 변수, 함수, 플래그 및 모든 것을 사용할 수 있는 상위 셸의 복사본입니다. 이러한 값을 수정해도 상위 항목에는 영향을 미치지 않습니다.
하위 쉘은 포크로 시작되지만 시작 구성에 지정된 쉘 기본값으로 재설정됩니다. 일부 코드(셸 또는 명령)를 실행하는 데 사용되는 프로세스가 됩니다.
서브셸은 변수 값에 액세스할 수 있습니다.
$ x=123; ( echo "$x")
123
서브셸은 다음을 수행할 수 없습니다(내보내지 않은 변수):
$ x=234; sh -c 'echo "x=$x"'
x=
답변3
서브쉘
서브쉘은 서브쉘이라고도 합니다. 하위 쉘은 상위 쉘과 다른 쉘에서 생성될 수 있습니다. 다음 명령을 사용하여 하위 쉘을 만들 수 있습니다.
1. 프로세스 목록
프로세스 목록은 괄호로 묶인 명령 그룹입니다. 예:
( pwd ; (echo $BASH_SUBSHELL))
그러면 현재 작업 디렉토리와 생성된 쉘 수가 인쇄됩니다.노트서브쉘을 호출하는 것은 비용이 많이 듭니다.
2. 협업 처리
백그라운드 모드에서 하위 쉘을 생성하고 하위 쉘에서 명령을 실행합니다.
coproc sleep 10
jobs
명령어를 입력하면
[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를 가진 하위 프로세스가 생성됩니다.