간단한 명령 실행에 대한 간단한 질문이 있습니다. 제가 이해한 바로는 ls
대화형 셸에 명령을 입력 하면
- 쉘은 명령을 해석합니다.
- Shell은 자식 프로세스를 생성하고 자식 프로세스에서 명령을 실행합니다.
- 쉘은 하위 프로세스가 완료될 때까지 기다립니다.
내 이해가 맞다면 쉘 프롬프트에 입력하는 간단한 명령은 하위 프로세스에서 실행되고 명령 결과는 현재 쉘 환경에 영향을 미치지 않습니다.
그렇다면 이와 같은 내장 명령은 어떻습니까 cd
? 현재 쉘의 작업 디렉토리가 cd
하위 프로세스에서 실행되고 현재 쉘 환경에 영향을 주지 않는 경우 어떻게 변경할 수 있습니까?
답변1
쉘은 단지 프로그램일 뿐이지만 시스템에서 중요한 역할을 합니다. Bash와 대부분의 다른 일반적인 쉘은 C로 구현됩니다. 가장 중요한 두 가지 네이티브 C시스템 호출하위 프로세스를 만드는 데 사용되는 프로세스는 fork()
및 입니다 exec()
. 이러한 기능은 일반적으로 셸을 포함한 고급 언어로도 구현됩니다.
fork()
"포크"는 호출 프로세스의 복사본을 하위 프로세스로 만듭니다. 이는 첫 번째 프로세스를 제외한 시스템의 거의 모든 프로세스가 작동하는 방식입니다(내부에) 시작: 이를 시작한 프로세스의 복사본입니다. 쉘 언어에는 실제로 기능이 없지만
fork
동일한 서브쉘을 생성하기 위한 구문이 포함되어 있습니다.exec()
C에는 실제로 호출이 없지만
exec()
관련 함수 그룹을 구어체로 참조합니다.man 3 exec
일반적으로 다음으로 시작하는 this 로 목록을 볼 수 있습니다.exec() 함수 시리즈는 현재 프로세스 이미지를 새로운 프로세스 이미지로 대체합니다.
이것이 정확히 하는 일입니다:바꾸다실행 파일(예: )에서
/usr/bin/ls
로드된 새 콘텐츠를 사용하여 현재 프로세스의 메모리 스택 부분을 정의합니다 . 이것이fork()
바로 새 프로세스를 생성할 때 먼저 이 작업을 수행해야 하는 이유입니다. 그렇지 않으면 호출 프로세스가 더 이상 이전 프로세스에서 벗어나 다른 프로세스가 실제로 생성되지 않습니다.
언뜻 보기에 이는 터무니없고 비효율적인 작업 방식처럼 들릴 수 있습니다. 명령을 사용하여 처음부터 새 프로세스를 생성하는 것은 어떨까요? 실제로 이는 다음과 같은 여러 가지 이유로 그다지 효과적이지 않을 수 있습니다.
fork()
커널이 사용하는 것처럼 결과 "복사본"은 다소 추상적입니다.쓰기 중 복사실제로 생성되어야 하는 것은 가상 메모리 맵뿐입니다. copy 가 즉시 호출되는 경우exec()
, 프로세스의 활동이 데이터를 수정하더라도 대부분의 데이터는 실제로 복사/생성될 필요가 없습니다. 프로세스는 데이터 사용에 필요한 작업을 수행하지 않기 때문입니다.하위 프로세스의 중요한 측면(예: 해당 환경)은 개별적으로 복사하거나 컨텍스트 등의 복잡한 분석을 기반으로 설정할 필요가 없습니다. 그들은 호출 프로세스와 동일하다고 가정하며 이는 우리에게 친숙한 상당히 직관적인 시스템입니다.
생성된 자식 프로세스에 "환경 복사"가 정확히 무엇을 의미하는지에 대한 자세한 설명은 다음을 참조하세요.내 대답은 여기에 있다.
그렇다면 cd와 같은 내장 명령은 어떻습니까?
다시 말하지만 C로만 구현됩니다. 및 와 chdir()
마찬가지로 이는 표준 C에 대한 Unix 플랫폼 확장의 일부이며 셸 명령의 기초입니다. 에서 :fork()
exec()
cd
man 2 chdir
chdir() 호출 프로세스의 현재 작업 디렉터리를 PATH에 지정된 디렉터리로 변경합니다.
이는 하위 프로세스가 필요하지 않으며 호출자에게 영향을 미칩니다. 쉘은 대화형 런타임입니다.통역사, 이는 명령을 내리면 쉘 언어로 작성된 코드를 실행한다는 의미입니다. 일반적으로 이 작업을 수행하기 위해 새 프로세스를 실행할 필요는 없으며 자체적으로 수행합니다.
답변2
그렇다면 cd와 같은 내장 명령은 어떻습니까? cd가 자식 프로세스에서 실행되는 경우
논리의 오류는 여기에 있습니다. cd
이는 쉘에 의해 특별히 해석되고 프로세스 내에서 "실행되는" 쉘 내장 명령입니다. 이 type
명령을 사용하여 명령이 내장 명령인지 여부를 확인할 수 있습니다.