출처 - https://github.com/jmxx219/CS-Study (opens in a new tab)
컴파일
프로그램 실행 과정
열심히 개발한 프로그램을 실행시키기 위해서는 크게 컴파일 - 링킹 - 로더 의 과정을 거쳐야 한다. 해당 과정 각각을 한번 알아보도록 합시다!
컴파일
컴퓨터가 이해하는 언어는 기계어입니다. 하지만 개발자들은 C, Java와 같은 프로그래밍 언어 즉, 고급언어를 통해 개발하기 때문에 고급언어를 기계어로 바꿔주는 과정이 필요하고, 이것을 컴파일이라 합니다.
컴파일 과정
4가지 과정을 통해 컴파일됩니다. 컴파일 과정속에 링킹 과정을 넣기도 하지만 링킹은 따로 자세히 알아보도록 하겠습니다.
◻️ 전처리
전처리기를 통해 소스코드(.c)를 전처리한 소스코드(.i)로 변환하는 과정으로 정말 코드만을 남기는 과정입니다.
대표적으로 세가지 과정을 거칩니다.
- 주석 제거
- 프로그램 실행에 필요없는 모든 주석을 삭제합니다.
- 라이브러리 삽입
- 라이브러리의 내용을 소스코드로 복사합니다. 라이브러리의 함수원형은 링킹과정에서 실제 함수가 정의되어 있는 오브젝트 파일과 결합됩니다.
- 매크로 치환 및 적용
- #define 지시문에 정의된 매크로를 저장하고 같은 문자열을 만나면 #define 된 내용으로 치환한다. 간단하게 말해 매크로 이름을 찾아서 정의한 값으로 전부 바꿔준다.
◻️ 컴파일
컴파일러를 통해 전처리된 소스코드(.i)를 어셈블리어 코드(.s)로 변환해주는 과정으로, 컴파일 과정의 핵심과정입니다.
◻️ 어셈블리
어셈블러를 통해 어셈블리어 코드(.s)를 오브젝트 파일(.o)로 변환해주는 과정이다.
링킹
컴파일된 소스 코드는 일반적으로 오브젝트 파일 형태로 만들어집니다. 하지만 오브젝트 파일 자체로는 프로그램을 실행시킬 수 없습니다. 이를 실행 가능한 형태로 변환하기 위해서는 링킹(linking)이라는 과정이 필요합니다.
오브젝트 파일은 실행 파일(exe 파일 등)로 변환되어야 프로그램을 실행할 수 있습니다. 링킹은 이러한 오브젝트 파일을 하나로 합치고, 필요한 라이브러리와 연결하여 실행 파일을 생성하는 과정입니다.
- 장점
- 모든 라이브러리을 하나의 소스파일에 넣어 오브젝트파일로 만드는 것이 아닌 작은 모듈로 나눠 관리하는 것을 가능하게 만들어준다.
링킹의 종류(정적 링킹, 동적 링킹)
정적 링킹(Static Linking)
정적 링킹이란 실행파일을 만들 때 사용하는 모든 라이브러리 모듈을 복사하는 방식입니다. 즉, 자신이 작성한 프로그램에서 A라는 외부 라이브러리를 사용했다면, A라는 외부 라이브러리에 대한 정보를 자신이 작성한 프로그램의 실행파일을 만들 때 복사해오는 방식입니다.
- 장점
- 실행파일안에 라이브러리의 정보가 포함되어 있어 동적링킹에 비해 빠르다
- 불일치에 대한 걱정을 하지 않아도 된다.
- 정적 링킹 프로그램에서 모든 코드는 하나의 실행 모듈에 담기기 때문이다.
- 단점
- 여러 개의 프로그램에서 같은 라이브러리를 사용하여도, 모든 실행파일에 같은 라이브러리의 정보가 담겨, 프로그램은 크기가 크고 메모리 효율이 좋지 않다.
- 외부 함수가 변경이 생길 경우 그 변화를 적용하기 위해서 다시 컴파일하여 다시 링킹을 해야 한다.
- 실행 가능한 목적파일을 만들 때 A에 관한 정보를 그냥 복사해왔기 때문에 외부 함수에 변화가 생겨도 다시 컴파일하지 않는 이상 적용이 안된다.
동적 링킹(Dynamic Linking)
동적 링킹이란 실행 가능한 목적 파일을 만들 때 프로그램에서 사용하는 모든 라이브러리 모듈을 복사하지 않고 해당 모듈의 주소만을 가지고 있다가, 런타임에 실행 파일과 라이브러리가 메모리에 위치될 때 해당 모듈의 주소로 가서 필요한 것을 들고 오는 방식이다. 런타임에 운영체제에 의하여 이루어진다.
- 장점
- 정적 링킹 방식보다 실행 가능한 목적파일의 크기가 작아, 메모리와 디스크 공간을 아낄수 있다.
- 여러 프로그램에서 외부 함수를 이용해도 외부 함수 정보는 하나만 있으면 된다.
- 목적파일에서는 외부 함수를 복사하는 것이 아닌 외부 함수가 있는 곳의 주소만 가리키고 있으면 된다.
- 외부 함수의 변화가 생겨도 변화를 적용하기 위해 다시 컴파일해 다시 링킹할 필요가 없다.
- 목적파일에 외부 함수에 관한 정보를 복사한 것이 아닌 외부 함수의 주소를 담았기 때문이다.
- 동적 라이브러리가 이미 존재하는 경우 로드되는 시간을 단축할 수 있다.
- 정적 링킹 방식보다 실행 가능한 목적파일의 크기가 작아, 메모리와 디스크 공간을 아낄수 있다.
- 단점
- 매번 주소를 따라가야 하는 오버헤드가 존재해, 정적 링킹 방식보다 느리다.
- 불일치에 대한 문제를 고려해야 한다.
- 사용하던 외부 함수가 시스템에서 제거가 된다면, 해당 프로그램의 실행 가능 목적파일에는 외부 함수의 주소가 있어서 존재하는 것처럼 동작을 해 제대로 실행될 수 없다.
오버헤드(overhead) : 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간·메모리 등
로더
컴파일 과정에서 만들어진 실행파일(.exe)을 cpu에 의해 실행시키기 위해서 메모리에 파일의 내용을 적재해야합니다. 이러한 역할을 하는것을 로더라고 합니다. 로더는 기본적으로 다음과 같은 기능을 차례로 수행하지만, 로더의 각 기능을 언어 번역 프로그램 또는 링커 등의 시스템 소프트웨어가 수행할 수도 있다.
- 할당(Allocation) : 실행 프로그램을 실행시키기 위해 기억장치 내에 옮겨놓을 공간을 확보하는 기능
- 연결(Linking) : 부 프로그램 호출 시 그 부 프로그램이 할당된 기억장소의 시작주소를 호출한 부분에 등록하여 연결하는 기능
- 재배치(Relocation) : 디스크 등의 보조기억장치에 저장된 프로그램이 사용하는 각 주소들을 할당된 기억장소의 실제 주소로 배치시키는 기능
- 적재(Loading) : 실행 프로그램을 할당된 기억공간에 실제로 옮기는 기능
로더의 종류
1) 컴파일 즉시 로더(Compile And Go)
- 별도의 로더 없이 언어 번역 프로그램이 로더의 기능까지 수행하는 방식이다.
- 연결 기능은 수행하지 않고 할당, 재배치, 적재 작업을 모두 언어 번역 프로그램이 담당한다.
2) 절대 로더(Absolute Loader)
- 목적 프로그램을 기억장소에 적재시키는 기능만 수행하는 로더로, 로더 중 가장 간단한 프로그램으로 구성되어 있다.
- 기억장소 할당이나 연결을 프로그래머가 직접 지정하며 한번 지정한 주기억장소의 위치는 변경이 어렵다.
3) 직접 연결 로더(Direct Linking Loader)
- 일반적인 기능의 로더로, 로더의 기본 기능 네 가지를 모두 수행하는 로더이다.
- 재배치 로더(Relocation Loader), 상대 로더(Relative Loader)라고도 한다.
4) 동적 적재 로더(Dynamic Loading Loader)
- 프로그램을 한꺼번에 적재하는 것이 아니라 실행 시 필요한 부분만을 적재하고 나머지 부분은 보조기억장치에 저장해두는 것으로, 호출 시 적재(Load-On-Call)라고도 한다.
- 프로그램의 크기가 주기억장치의 크기보다 큰 경우에 유리한 방법이다.
Ref
- https://seohs.tistory.com/259 (opens in a new tab)
- https://live-everyday.tistory.com/67 (opens in a new tab)
- https://live-everyday.tistory.com/69 (opens in a new tab)
- https://hbesthee.tistory.com/1410 (opens in a new tab)
- https://d2.naver.com/helloworld/1230 (opens in a new tab)
- https://steady-snail.tistory.com/67 (opens in a new tab)
- https://www.sktenterprise.com/bizInsight/blogDetail/dev/2434 (opens in a new tab)