0. 개요
컴퓨터 시스템은 하드웨어와 시스템 소프트웨어 컴포넌트를 가지고 있다.
프로그래머들은 이들 컴포넌트들이 어떻게 동작하고 프로그램 성능과 정확성에 어떤 영향을 주는지 이해해야한다.
컴포넌트란?
독립적인 단위 모듈을 뜻한다. 이는 독립적인 기능을 수핸하며 추후 교체 가능함을 의미한다.
모듈이란?
본체에 대한 독립된 하위 단위를 의미한다.
컴포넌트 vs 모듈
모듈은 정적인 구조를 의미하며, 가장 첫번째, 즉 맨 앞에 위치하는 구현 단위이다.
컴포넌트는 런타임에 독립적으로 배포되고 실행되는 단위이다. 따라서 런타임 개체를 참조한다.
컴포넌트와 모듈의 구분을 가장 쉽게 이해하는 예는 '서버-클라이언트' 구조이다.
컴퓨터 시스템에 서버와 클라이언트 모듈이 존재하고,
하나의 서버에 10개의 클라이언트가 연결된 11개의 컴포넌트를 생각하면 된다.
앞으로 우리는 어떤 내용을 공부하게 될까?
우리는 컴퓨터가 숫자를 표시하는 방법때문에 생기는 이상한 숫자 에러를 피하는 방법 같은 기술을 배우며,
컴파일러가 프로시저 호출을 어떻게 구현하는지,
버퍼 오버플로우의 원리는 어떤것인지,
C코드의 최적화는 어떻게 할 것인지 등에 대해서 공부 한다.
시스템에 관한 공부는 이 다음의 프로그램 부터 시작한다.
#include<stdio.h>
int main(){
printf("hello, wolrd\n");
return 0;
}
프로그램이 프로그래머에 의해 만들어지고, 시스템에서 실행되고, 메세지를 출력하고 종료될 때 까지의 수명주기를 추적하는 것으로 부터 시작할 것이다.
1. 정보의 구성
위의 우리가 작성한 hello.c 소스코드를 살펴보자.
이 소스코드는 0또는 1로 표시되는 비트들의 연속으로 표현되어 있다.
또한 우리가 짠 문자로 표시된 소스코드를 컴퓨터 시스템은 아스키 표준을 사용하여 표현하며,
각 문자를 바이트 길이의 정수값으로 나타낸다.
따라서 우리가 작성한 소스코드와 같이 아스키 문자들로만 이루어진 파일들을 텍스트 파일,
그 외의 것들은 바이너리 파일이라고 부른다.
이 표시방법은 기본 개념에 대해서 확실히 살펴볼 수 있다.
메모리 상 프로그램, 데이터, 네트워크를 통해 전송되는 데이터 등 시스템 정보는 비트들로 표시된다는 것이다.
2. 소스코드가 프로그램이 되는 과정
위에서 짠 hello.c를 시스템에서 실행시키려면 C로 짜여진 소스코드를 컴퓨터가 알아들을 수 있도록 기계어 인스트럭션들로 번역해야한다.
인스트럭션(instruction) : 명령어의 집합
이는 실행가능 목적 프로그램으로 합쳐져서 바이너리 디스크 파일로 저장된다.
즉, 컴파일 된다는 의미다.
C를 컴파일 하는 명령어는 대표적으로 다음이 있다.
gcc -o hello hello.c
gcc 컴파일러의 명령어다.
이 gcc 컴파일러는 소스파일 hello.c를 읽어서 실행파일 hello로 만들어주는 역할을 한다.
그 과정에서 진행되는 단계는 다음과 같다.
1. 전처리기
2. 컴파일러
3. 어셈블러
4. 링커
* 전처리 단계 :
소스코드에서 #으로 시작하는 디렉티브(번역 규칙)에 따라 수정한다.
즉 위의 소스코드이 경우 #include<stdio.h> 의 경우 전처리기에 의해서 시스템 헤더파일인 stdio.h를 프로그램 문장에 직접 삽입하라고 지시한다.
즉, 우리가 편의상 #include<stdio.h> 라는 구문을 넣어서 stdio 헤더를 사용했다면 전처리 단계에서는 직접 헤더의 내용들을 소스코드에 변환하여 대입한다는 의미다.
이 과정에서 hello.i 파일이 생성된다.
* 컴파일러 :
텍스트 파일인 hello.i 파일을 텍스트 파일인 hello.s 파일로 번역한다.
이 과정에서 어셈블리어 프로그램이 저장된다.
* 어셈블러 :
컴파일러가 생성한 hello.s 어셈블리 파일을 기계어 인스트럭션으로 번역하며, 재배치 가능 목적프로그램의 형태로 묶어서 hello.o라는 목적파일을 생성한다.
재배치 가능 이란?
기억장소 내에서 어느 부분이나 자리잡을 수 있는 성질을 의미한다.
* 링커 :
별도의 목적파일에 들어있는 함수들, hello.c의 경우 printf 함수를 호출한다.
즉, 기존에 소스코드에서 필요한 기본 함수들을 연결해주는 과정이다.
따라서 prntf.o 파일에 들어있는 printf 함수를 hello.o 파일과 링크해주는 역할을 하며,
그 결과 실행가능한 목적파일, 즉 실행파일로 메모리에 적재되어 시스템에 의해 실행된다.
3. 컴파일 시스템에 이해가 중요한 이유
hello.c처럼 간단한 프로그램의 경우, 컴파일 시스템이 알아서 효율적인 기계어 코드로 만들어 줄 것이다.
하지만 프로그램의 성능 최적화를 위해 기본적인 이해와 컴파일러의 번역 방식은 알 필요가 있다.
이러한 내용들은 다음의 궁금증들을 해결할 것이다.
* while과 for 둘중 어떤 것이 효율적일까?
* switch문은 if-else 문을 얼마나 나열할 때 사용하는 것이 좋을까?
* 함수 호출시 발생되는 오버헤드는 얼마나 될까?
* 등등..
오버헤드(overhead) : 어떤 처리를 하기위해 들어가는 간접적인 시간
따라서 우리는 기초적인 컴파일 시스템에 대하여 이해해야한다.
결국 우리가 작성하는 코드를 컴퓨터에게 이해시키는 일은 컴파일러가 하기 때문이다.
2에서 계속...
'Computer System' 카테고리의 다른 글
| 1. 컴퓨터 시스템의 시작(3) (0) | 2021.02.01 |
|---|---|
| 1. 컴퓨터 시스템의 시작(2) (0) | 2021.01.04 |