소스파일 (. c)을 실행파일로 번역하기 위해 4단계( 전처리기, 컴파일러, 어셈블러, 링커) 단계를 거치는데 위 단계를 합쳐
컴파일 시스템이라 부른다.
#include <stdio.h>
int main()
{
printf("Hello, World \n");
return 0;
}
전처리 단계 (pre-processor) :
전처리기(CPP)는 C프로그램을 #문자로 시작하는 directive에 따라 수정한다.
위의 예에서 보면 #incluide<stdio.h>는 전처리기에 시스템 헤드 파일(stdio.h)을 프로그램 문장에 직접 삽입하라고 지시한다. 그 결과 (. i )로 끝나는 새로운 C 프로그램이 생성된다.
컴파일 단계 (compiler) :
텍스트파일 (. i) 프로그램 파일을 텍스트 파일 (. s) 파일로 번역하며 이 파일에 어셈블리어 프로그램이 저장된다.
(텍스트파일이란 오로지 아스키 문자들로만 이루어진 파일이며 그 외 다른 모든 파일은 바이너리 파일이라 한다.)
사람이 작성한 코드를 컴퓨터가 인식할 수 있는 언어(어셈블리어)로 번역을 해주는 과정이다. 컴퓨터가 인식할 수 있는 기계어란 즉 0,1의 디지털 값이다.
어셈블리 단계 (assembler):
어셈블러는 (.s)를 기계어 인스트럭션으로 번역, 이들을 재배치 가능한 목적 프로그램(object program)의 형태로 묵어 (. o)라는 목적 파일에 결과를 저장한다. 이 파일은 main 함수의 인스트럭션을 인코딩하기 위한 17바이트를 포함하는 바이너리 파일이다.
링크 단계(linker):
위의 예제 프로그램이 C컴파일러에서 제공하는 표준 C 라이브러리에 있는 printf함수를 호출하고 있다. printf함수는 이미 컴파일된 별도의 목적 파일인 printf.o에 들어있다.
따라서 우리는 이 printf.o파일을 hello.o파일과 어떤 형태로든 결합하여야 한다. 링커 프로그램이 이 통합작업을 수행한다.
그 결과 hello 파일은 실행가능 목적 파일(실행파일 (. exe) )로 메모리에 적재되어 시스템에 의해 실행된다.
즉 링크는 목적파일과 라이브러리 파일을 하나의 프로그램으로 합치는 작업이다.
linux 커맨드:
gcc -o hello hello.c
<hello.c라는 소스파일을 읽어 실행파일인 hello로 번역해라>
왜 컴파일 시스템의 동작이해가 중요한가?
- 프로그램 성능 최적화
- 링크에러이해
- 보안약점 피하기
컴파일러가 여러가지 C 구조를 어떻게 기계어로 번역하는지 이해하고 어떻게 C컴파일러가 배열을 메모리에 저장하는지 등 메모리 시스템의 계층적 본성에 대해 학습한다면 어떻게 해야 효율적으로 C프로그램이 실행될 수 있는지 배울 수 있다. -> 프로그램 성능 최적화
링크에러를 이해하면 큰규모의 소프트웨어 시스템을 빌드할 경우 도움이 된다.
큰 규모의 프로그램을 개발하는 프로그래머는 종종 모듈이 없어서, 라이브러리가 없어서, 또는 맞지 않는 라이브러리 버전 때문에 링커 에러를 발생시킨다. 이때 어떻게 링커가 참조를 해결해 나가는지 라이브러리가 무엇인지, 어떻게 링커가 참조를 해결하기 위해 라이브러리를 사용하는지 등을 이해한다면 에러를 만나도 당혹스럽지 않을 것이다.
보안약점의 주요원인으로는 버퍼 오버플로우 취약성이다. 안전한 프로그래밍을 배우는 첫 단계는 프로그램 스텍에 데이터와 제어 정보가 저장되는 방식때문에 생겨나는 영향을 이해하는 것이다.
'Computer System' 카테고리의 다른 글
네트워크_TCP/IP (0) | 2021.12.22 |
---|---|
네트워크_OSI 7계층 (0) | 2021.12.21 |
Computer network_Client-Server Programming Model (0) | 2021.12.19 |
가상메모리 (0) | 2021.12.14 |
메모리시스템 (0) | 2021.12.13 |