본문 바로가기
TIL & WIL

[TIL] 크래프톤 정글 1주차 CS:app 2(C 프로그램 컴파일 이후 실행 과정)

by 적용1 2024. 3. 27.
728x90

크래프톤 정글 1주차를 하며 CS:app(Computer Systems : A Programmer's Perspective)를 목차 1.4 까지 읽으며 공부하고 이해한 내용을 정리한 글이다.

(앞 글 : https://jeokyong-development.tistory.com/5)

 

1.4

앞 글을 보고 왔다면 현재 hello.c가 컴파일 시스템에 의해 컴파일되어 실행 가능 목적 파일 hello가 만들어졌다는 것을 알고 있을 것이다.

이 hello 파일을 유닉스에서 실행하기 위해서는 '쉘'이라는 응용프로그램에 이름을 다음과 같이 입력해야한다.

linux에서의 명령 프롬프트

쉘은 커맨드라인 인터프리터로 프롬프트를 출력하고 명령어 라인을 입력받아 해당 명령을 실행한다.

위와 같은 경우와 같이 명령어가 아니면 실행 파일의 이름으로 판단하고 그 파일을 로딩해서 실행해준다.

1.4.1

hello와 같은 프로그램을 실행할 때 무슨 일이 일어나는지 알기 위해서는 다음과 같은 전형적인 시스템에서의 하드웨어 조직을 이해할 필요가 있다.

인텔 시스템 계열을 모델로 한 하드웨어 구성

1장에서는 여기 나와있는 구성 요소들을 간략하게 설명하고 자세한 내용은 뒷 장에서 설명하는 것 같다. 그러므로 이 글에서도 간략한 설명만 정리하겠다.

■ 버스 ( Buses )

- 시스템 내를 관통하는 전기적 배선군을 버스라고 하며, 컴포넌트들 간에 바이트 정보들을 전송한다.

 

- 일반적으로 워드(word)라고 하는 고정 크기의 바이트 단위로 데이터를 전송하도록 설계되었다.

 

- 1개를 워드를 구성하는 바이트 수는 시스템 마다 보유하는 기본 시스템 변수이다

ex) 워드가 4byte라면 32비트 시스템, 8byte라면 64비트 시스템

■  입출력 장치

- 시스템과 외부 세계의 연결을 담당한다(위 사진에서는 입력용 마우스, 키보드, 출력용 디스플레이, 데이터와 프로그램의 장기 저장을 위한 디스크 드라이브가 이에 해당한다).

 

- 각 입출력 장치는 입출력 버스와 컨트롤러 또는 어댑터를 통해 연결된다.

└> 두 장치의 차이는 패키징(packaging)에 있다.

└> 컨트롤러는 디바이스 자체가 칩셋이거나 시스템의 인쇄기판(이후 머더보드)에 장착된다.

└> 어댑터는 머더보드의 슬롯에 장착되는 카드

■ 메인 메모리

- 프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장 장치

 

- 물리적으로 DRAM(Dynamic Random Access Memory) 칩들로 구성되어있다.

 

- 논리적으로 연속적인 바이트들의 배열로, 각각 0부터 시작해서 고유의 주소(배열의 인덱스)를 가지고 있다.

 

- 기계어 인스트럭션 마다 다양한 바이트 크기를 가진다.

ex) C 프로그램에서 data type마다 크기가 다른 것

└> x86-64 컴퓨터에서 short형 : 2byte, int / float : 4byte, long / double : 8byte

■ 프로세서

- 주처리 장치(CPU)(= 프로세서)는 메인 메모리에 저장된 instruction들을 해독(실행)하는 엔진이다.

 

- 중심에 워드 크기의 저장장치(= 레지스터)인 프로그램 카운터(PC)가 있는데 어느 한순간에 PC는 메인 메모리의 기계어 instruction을 가리키게 된다.

 

- 프로세서는 전원이 공급되는 동안 PC가 가리키는 곳의 instruction을 반복적으로 실행하고 PC 값이 다음 instruction의 위치를 가리키도록 업데이트한다.

 

-프로세서는 자신의 인스트럭션 집합 구조(instruction set architecture)로 정의되는 단순한 인스트럭션 실행 모델을 따라 작동한다.

 

이 동작들은 메인 메모리, 레지스터 파일, 수식 / 논리 처리기(ALU) 주위를 순환하는 구조이다.

- 레지스터 파일은 각각 고유의 이름을 갖는 워드 크기의 레지스터 집합으로 구성되어 있고, ALU는 새 데이터와 주소 값을 계산한다.

 

- CPU가 실행하는 단순한 작업의 예

 · 적재(Load) : 메인 메모리에서 레지스터로 1 byte 혹은 word를 이전 값에 덮어쓰는 방식으로 복사

 · 저장(Store) : 레지스터에서 메인 메모리로 1 byte 혹은 word를 이전 값을 덮어쓰는 방식으로 복사 

 · 작업(Operate) : 두 레지스터의 값을 ALU로 복사하고 두 개의 워드로 수식 연산을 수행한 뒤, 결과를 덮어쓰는 방식으로

                             레지스터에 저장

 · 점프(Jump) : instruction 자신으로부터 1개의 워드를 추출하고, 이 것을 PC에 덮어쓰기 방식으로 복사

 

- 최신 프로세서는 프로그램의 실행 속도를 높이기 위해 위 방식보다 훨씬 더 복잡한 방식을 사용한다.

1.4.1 hello 프로그램의 실행 과정

1. 쉘에 .\hello 입력

 

2. 쉘이 각각의 문자를 레지스터에서 읽어들인 후, 다음 그림과 같이 메모리에 저장

키보드를 통해 입력한 문자를 레지스터를 통해 메모리에 저장하는 과정

 

3. 키보드에서 엔터를 누르면 쉘이 명령 입력을 끝마쳤다는 것을 알게 된다.

 

4. 파일 내 코드와 데이터를 복사하는 인스트럭션을 실행하여 실행파일 hello를 디스크에서 메인 메모리로 로딩한다.(이 때, 데이터에는 출력되는 "hello, world\n"이 포함되어있다.)

 

5. 직접 메모리 접근(DMA)(6장에서 논의) 기법을 이용하여 데이터가 프로세스를 거치지 않고 디스크에서 메인 메모리로 직접 이동한다.

DMA를 통해 CPU를 거치지 않고 디스크에서 메인 메모리로 데이터가 이동하는 과정

 

6. hello 목적 파일의 코드와 데이터가 메모리에 적재된 후, 프로세서가 hello 프로그램의 main 루틴의 기계어 인스트럭션을 실행한다.

이 때의 인스트럭션은 "hello, world\n" 스트링을 메모리부터 레지스터 파일로 복사하고, 거기로부터 디스플레이 장치로 전송한다.

출력되는 string이 main memory에서 CPU를 거쳐 디스플레이로 전달되는 과정

 

 

1장은 간략하게 뒤에 어떤 내용이 나오는지 소개하는 느낌이라 간략하게 정리만 해보았다.

자세한 내용은 앞으로 공부를 해가며 정리하여 다시 글을 작성해 보겠다.

마지막으로 이 글을 작성하는 바탕이 된 수기로 작성한 파일을 올려놓겠다.

728x90