예를 들어, bash는 /bin/bash 아래에 있습니다. 이는 명령임을 의미하며 각 명령에는 표준 입력, 표준 출력, 표준 오류의 세 가지(0,1,2) 구멍이 있습니다.
이것이 쉘에도 100% 사실인가요? 아니면 명령이나 프로세스로서의 쉘의 특별한 의미 때문에 다른 것입니까?
답변1
다른 프로그램과 똑같습니다. 이를 통해 다른 프로그램처럼 I/O를 리디렉션하고 파이프할 수 있습니다.
echo "cat filename" | bash
명령은 파이프에서 표준 입력을 읽을 때 실행됩니다 cat filename
.bash
bash -c "echo foo" > filename
명령 echo foo
이 실행되고 출력이 파일로 리디렉션됩니다.
Unix에서는 쉘에 "특별한" 것이 없습니다. 이는 다른 프로그램을 실행하는 것이 주요 목적인 일반 프로그램일 뿐입니다.
답변2
몇 가지 용어를 구별해 보겠습니다.
ㅏ주문하다쉘에 입력하는 내용입니다. 그것은별명또는쉘 기능, 또는 다음을 참조할 수도 있습니다.실행 가능 파일.
하나실행 가능 파일될 수 있습니다바이너리 실행 파일(즉, 기계어 코드를 직접 포함하는 코드) 또는스크립트. 스크립트에는 bash 스크립트, sh 스크립트, perl 스크립트, awk 스크립트, sed 스크립트, python 스크립트 등이 포함됩니다. 외.
스크립트의 처음 2바이트(실행 파일로 직접 실행되는 경우)는 이어야 합니다 #!
. 이는 개행 문자를 읽을 때까지 커널에 더 많은 바이트를 읽도록 신호를 보내는 "마법의 숫자"입니다. ㅏ바이너리 실행 파일, 공백으로 구분된 하나의 인수(예: #!/bin/awk -f
)를 가질 수 있으며 다음을 실행합니다.저것바이너리 실행 파일, 스크립트 자체의 경로가 매개변수로 전달됩니다.
궁극적으로 커널이 실제로 실행할 수 있는 유일한 것은 바이너리 실행 파일인 기계어 코드뿐입니다. sh, bash, perl, python, awk 등과 같은 바이너리 실행 파일입니다. 외. ~라고 불리는통역사. 그들은 스크립트를 해석하고 해당 지침을 실행합니다. 하지만 실행되기 위해서는 기계어 코드 자체에 존재해야 합니다.
프로그램(바이너리 실행 파일)이 실제로 커널에 의해 실행될 때 다음과 같이 작동합니다.프로세스. 바이너리 실행 파일은 지침이 포함된 파일일 뿐입니다. ㅏ프로세스보다 구체적으로 "프로그램의 실행 인스턴스"이며 관련 메모리, 환경 변수, 프로세스 ID(PID)와 함께 커널에 내장된 추상화입니다.파일 설명자입력 및 출력뿐만 아니라 기타 속성에도 사용할 수 있습니다. 실행 파일을 "동시에" 여러 번 실행할 수 있습니다(실제로 단일 코어 시스템에서는 동시에는 아니지만 커널이 CPU 사이클을 할당하는 방식으로 인해~인 것 같다동시에) 실행 중인 각 인스턴스는 모두 동일한 프로그램의 인스턴스이더라도 서로 다른 프로세스가 됩니다.
0, 1, 2(표준 입력, 표준 출력, 표준 오류)는파일 설명자. 솔직히 말해서 그들은 관습에 의해서만 존재합니다. C를 사용하면 이러한 파일 설명자를 제공하지 않고도 다른 프로그램을 시작(실행)(다양한 바이너리 실행 파일 실행)하는 프로그램을 만들 수 있습니다. 하지만,표준 프로그램은 파일 설명자 0, 1, 2를 사용할 수 있다는 가정하에 작성되었으므로 아마도 오류가 발생하고(대부분의 경우) 프로그램이 제대로 작동하지 않을 것입니다.
이것을 완전히 이해하려면 다음을 이해해야 합니다.프로세스가 발생하는 방법. 일종의 탄생의 기적과도 같습니다. ;) 모든 프로세스는 다음에 의해 실행되어야 합니다.다른프로세스. 시스템을 부팅할 때 첫 번째 프로세스가 어떻게 시작되는지 걱정하지 마십시오. PID 1이 있는 프로세스를 "init"라고 하며 운영 체제 실행에 필요한 기타 기본 프로세스를 시작합니다.
프로세스가 다른 프로세스를 시작하는 방법에는 두 가지 기본 단계가 있습니다.십자가그리고구현하다. 둘 다 시스템 호출입니다. 즉, 프로세스에서 보낸 작업/요청입니다.커널로커널만이 이를 실제로 달성할 수 있습니다.
"포크"는 (간단히) "커널, 복사본을 만들어 주세요"를 의미합니다. ("Me"는 실행 중인 프로세스입니다.) 커널은 프로세스의 파일 설명자, 메모리, 실행 상태(인스턴스인 프로그램을 구성하는 명령을 따르는 동안 있었던 위치), 환경 등 프로세스의 완전한 복사본을 만듭니다. 변수 등등. 따라서 이는 해당 프로세스의 "복제본"입니다. 이제 원본과 사본을 어떻게 구별합니까? 단 한 가지: 시스템 호출의 반환 상태입니다 fork
. 하위 프로세스는 "0"(성공)을 얻고 상위 프로세스는 새로 생성된 하위 프로세스의 PID를 가져옵니다. 따라서 이 반환 상태를 확인함으로써 각 프로세스는 지금 수행해야 할 작업을 파악할 수 있습니다(왜냐하면 동일한 지침 세트를 따른다는 점을 기억하십시오!).
"Exec"은 실제로 "execve()"입니다. 간단히 말해서, 커널에 "커널을 부탁합니다.바꾸다나(나는 프로세스입니다)는 ______ 파일에 프로그램 인스턴스를 지정했습니다. "그리고 프로그래머도 지정했습니다.논쟁새로운 프로세스에는환경(환경 변수 배열)이 있을 것입니다.
따라서 쉘에 명령을 입력하면 실제로 발생하는 일은(대부분의 경우 쉘 내장과 같은 특수한 경우를 무시하고 cd
) 쉘(실행 중인 프로세스)입니다.포크,그런 다음임원사용자가 지정하는 명령입니다.
출력 또는 입력 리디렉션을 수행한 경우 /bin/echo hello > /dev/null
포크된 하위 프로세스exec
에코를 하기 전에파일 설명자 1(이 경우)이 /dev/null
터미널이나 이전의 터미널 대신 바인딩되도록 파일 설명자를 적절하게 조정합니다.
따라서 실행 중인 실행 파일 인스턴스에는 /bin/bash
사용 가능한 파일 설명자 0(입력을 읽을 수 있음), 파일 설명자 1(출력을 쓸 수 있음) 및 파일 설명자 2(출력을 읽을 수 있음)가 있을 것으로 예상됩니다. 작성) 오류) 메시지 및 유사한 입력/출력을 읽고 씁니다.