쉘은 어떻게 프로그램을 실행합니까?


11

gcc를 사용하여 프로그램을 컴파일하고 bash 쉘에서 실행하려고하면 정확한 단계 순서와 bash가 실행됩니다.

내가 알고 fork(), execve(), loader, dynamic linker(그리고 다른 것들) 관여하지만, 캔 누군가가 단계의 정확한 순서와 일부 적합한 독서 참조를 제공?

편집하다:

대답에서, 그 질문은 많은 가능성을 암시 할 수있는 것 같습니다. 간단한 경우로 좁히고 싶습니다.

(test.c는 hello world를 인쇄합니다)

$ gcc test.c -o test
$ ./test

위의 경우 ( ./test) 의 단계 , 특히 일부 하위 프로세스의 bash 시작 프로그램과 관련하여로드, 링크 등을 수행하는 단계는 무엇입니까?


4
난 당신이 읽을 초대 lwn.net/Articles/630727
— cuonglm

3
왜 strace bash -c 'test'를 시도하지 않습니까?
— Sergiy Kolodyazhnyy

2
괜찮은 운영 체제 교과서가 OP의 좋은 리소스가 될 것 같습니다. 이와 같은 개별적인 질문을 통해 운영 체제의 작동 방식을 배우려고하는 것은 생산적인 프로세스가 아닐 수 있습니다.
— Barmar

쉘의 최소한의 예를 보는 것이 유용합니다 : brennan.io/2015/01/16/write-a-shell-in-c
— jinawee

답변:


5

실제 프로그램이 실행되기 전에 먼저 확장 / 해석되는 셸 별명이나 함수가있을 수 있고, 정규화 된 파일 이름 ( /usr/libexec/foo)과 모든 디렉토리에서 찾을 수있는 것의 차이점이 있기 때문에 정확한 순서는 다를 수 있습니다. 의 PATH환경 변수 (단지 foo). 또한, 실행의 세부 사항으로, 문제를 복잡하게 할 수있다 foo | bar | zot(몇 개의 쉘에 대한 더 많은 작업이 필요합니다 fork(2), dup(2)물론,와 pipe(2)같은 것이 있지만, 다른 시스템 호출 사이에서) exec foo훨씬 적은 작업이 쉘은 단지 자신을 대체로 새로운 프로그램 (즉, 그렇지 않습니다 fork). 또한 프로세스 그룹 (특히 포 그라운드 프로세스 그룹, 모든 PID가 먹는 그룹)도 중요합니다.SIGINT누군가가 Ctrl+ C에서 세션을 시작 하고 세션 및 작업이 백그라운드에서 실행 될지 모니터링되는지 ( foo &) 또는 백그라운드에서 무시 되는지 ( foo & disown) I / O 리디렉션 세부 사항은 예를 들어 표준 입력이 쉘 ( foo <&-)에 의해 닫히 거나 파일이 stdin ( foo < blah)으로 열리는 지 등을 변경합니다 .

strace이 과정에서 수행 된 특정 시스템 호출에 대한 정보는 이와 비슷하며 각 호출에 대한 매뉴얼 페이지가 있어야합니다. 적절한 시스템 레벨 읽기는 Stevens의 "UNIX 환경에서의 고급 프로그래밍"의 여러 장이 될 것이며 쉘 책 (예 : "Bash에서 Z Shell로")은 쉘의 측면을 더 자세히 다룰 것입니다.


간단한 사례로 좁히기 위해 질문을 수정했습니다.
— Jake

1

이미 실행중인 (코드 명확성을 위해) 교과서 예제 쉘 (동적 링커가 수행됨)을 가정 할 때 언급 한 명령을 수행하려면 쉘에서 다음 시스템 호출을 수행해야합니다.

  • 읽기 :이 경우 다음 명령을 얻습니다 gcc
  • 포크 : 두 가지 과정이 필요합니다. 우리는 부모가 pid 500을 가지고 있고 그림을 위해 아이를 가지고 있다고 가정합니다.
  • 부모는 wait (501)를 호출하고 자식은 exec를 호출합니다. 이 시점에서 쉘은 더 이상 pid 501에서 실행되지 않습니다. gcc는 최소한 open, close, read, write, chmod, fork, exec, wait 및 exit를 포함하여 많은 시스템 호출을 수행합니다.
  • gcc 호출이 종료되면 대기가 반환되고 프롬프트가 표시되도록 쓰기가 호출되고 프로세스가 반복됩니다.

물론 더 복잡한 명령은이 기본 시퀀스에 더 복잡한 문제를 추가합니다. 기본 합병증의 간단한 두 가지 예는 포크와 exec 사이에 열린 dup 시퀀스가 ​​삽입되고 대기가 생략 된 백그라운드 프로세스와 또 다른 대기가 sigchld 핸들러에 추가되는 기본 io 리디렉션입니다.


작은 추가 사항 :로드 및 동적 링크에 대한 질문입니다. 정적으로 링크 된, 즉 실제로 프로그램 파일에 포함 된 모든 코드는 프로그램이 시작되기 전에 커널에 의해 수행됩니다. 동적으로로드 된 라이브러리, 즉 별도의 파일은 main ()을 시작하기 전에 프로그램 자체에서 처리합니다. 이에 대한 코드는 gcc에 의해 자동으로 추가됩니다.
— Stig Hemmer

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