Object File과 Linker의 역할
Object File (객체 파일)
컴파일러가 소스 코드를 변환한 결과물로, 크게 세 가지 유형으로 나눌 수 있습니다.
1. Relocatable Object File
- 다른 파일에 정의된 함수나 전역 변수를 참조할 수 있는 객체 파일입니다. 파일 내부에 정의되지 않은 심볼은
?
와 같은 표시로 나타나며, 나중에 Linker가 연결을 통해 참조를 해결해줍니다.
2. Executable Object File
- 실행 가능한 완전한 파일로, 모든 심볼이 연결되어 메모리에 로드 후 실행할 준비가 된 상태입니다.
3. Shared Object File
- 여러 프로그램에서 공유 가능한 라이브러리 파일입니다. 프로그램 실행 시 동적으로 로딩되어 메모리 사용을 효율화할 수 있습니다.
Linker의 역할
Linker는 여러 개의 객체 파일을 하나의 실행 파일로 연결합니다. 이를 통해 각 객체 파일이 참조하는 외부 심볼을 해결하고, 메모리에서 실제 주소로 할당합니다.
Linker의 주요 작업
- Symbol Resolution (심볼 해결) -각 객체 파일에 정의되지 않은 외부 참조를 해결하여 모든 심볼이 정확한 위치를 가지도록 합니다.
- Relocation (재배치) - 객체 파일이 메모리에 로드될 때 각 심볼과 코드가 실제 메모리 주소에 맞게 재배치됩니다. 이를 통해 객체 파일이 각자의 메모리 영역을 가지며 실행될 수 있게 합니다.
Linker가 필요한 이유
- 모듈성 (Modularity)- 코드를 여러 모듈로 나누어 작성하고 컴파일한 후 Linker를 통해 하나의 실행 파일로 결합할 수 있습니다. 이로 인해 코드 유지보수와 모듈화가 용이해집니다.
- 효율성 (Efficiency) - 여러 객체 파일을 필요할 때만 연결하고, 프로그램이 필요로 하는 라이브러리와 파일만 로드하여 메모리 사용을 최적화합니다.
Linker의 종류
- Static Linker (정적 링크) - 컴파일 단계에서 모든 심볼을 연결하여 실행 파일을 생성합니다. 실행 파일이 라이브러리를 포함하고 있어 독립적으로 실행 가능하지만, 파일 크기가 커질 수 있습니다.
- Dynamic Linker (동적 링크) - 프로그램 실행 시 필요한 공유 라이브러리를 메모리에 로드하여 연결합니다. 실행 파일 크기는 작아지지만 프로그램 실행 중 추가 로드가 필요하므로 실행 속도에 영향을 줄 수 있습니다.
Object File의 구성 (ELF 포맷 예시)
Object 파일은 다양한 섹션으로 구성되며, 대표적으로 다음과 같은 섹션을 포함합니다.
- Data Section (데이터 섹션) - 초기화된 전역 변수가 저장되는 영역입니다.
- BSS Section (BSS 섹션) - 초기화되지 않은 전역 변수의 메모리 공간입니다. 메모리 효율성을 위해 이 변수들은 실행 시
0
으로 초기화됩니다.
Object의 생명 주기와 스코프
Life: 객체가 메모리에서 존재하는 기간으로, 예를 들어 스택 프레임이 pop되면 함수 내 로컬 변수의 life가 종료됩니다.
Scope: 객체에 접근할 수 있는 영역을 의미합니다. 예를 들어 함수 내 로컬 변수의 scope는 함수 내부로 제한됩니다.
변수 종류 | 설명 |
---|---|
Local Variables | 함수 내부에 선언된 변수, scope는 함수 내로 제한됨 |
Global Variables | 함수 외부에 선언된 변수, 프로그램 전체에서 접근 가능 |
Static Variables | 함수 외부에 선언되며 파일 내에서만 접근 가능 |
Static Local Variables | 함수 내부에 선언되며, 함수 호출 이후에도 유지됨 |
Symbol
심볼은 함수나 변수 등 메모리의 주소가 필요한 모든 대상을 나타냅니다. Linker는 세 가지 종류의 심볼을 관리합니다.
1. Global Symbol - 다른 객체 파일에서 접근할 수 있는 함수나 변수입니다.
2. External Symbol - 현재 객체 파일에 정의되어 있지 않지만, 다른 객체 파일에서 정의된 심볼입니다.
3. Local Symbol - 객체 파일 내부에서만 접근 가능한 심볼입니다.
Compiler Driver의 역할
Compiler Driver는 컴파일과 링크 과정을 한 번에 수행할 수 있도록 돕는 도구입니다. 예를 들어 gcc와 같은 컴파일러를 사용하면 소스 코드를 컴파일하고 링크하여 실행 파일을 만드는 과정을 한 번의 명령으로 실행할 수 있습니다.
Symbol Table과 Relocation
컴파일러는 각 소스 파일을 컴파일하여 Object File로 변환하는 과정에서 Symbol Table을 생성합니다. Symbol Table에는 함수 이름이나 전역 변수와 같은 심볼들이 정의되며, 이들은 파일 내 상대적 위치로만 지정됩니다. 이 Object File은 Linker에 의해 실제 메모리 주소가 할당되기 전까지 상대적 주소 상태에 있습니다. 따라서 이를 Relocatable Object File이라고도 합니다.
Strong and Weak Symbols
1. Symbol Resolution: 심볼이 정의된 파일과 함수를 정확히 매칭하여 연결하는 작업입니다.
2. Strong Symbol: 프로시저나 초기화된 글로벌 변수와 같은 중복이 허용되지 않는 심볼입니다.
3. Weak Symbol: 초기화된 값이 없는 변수 등 중복을 허용하는 심볼입니다.
링커는 심볼의 강도(strong/weak)를 알고 있으며, 컴파일러가 이 정보를 제공합니다.
Linker의 Symbol Resolution Rules
Strong Symbol은 하나만 존재해야 합니다.
Weak Symbol은 중복을 허락하되, 동일한 이름의 Strong Symbol이 있으면 Strong Symbol을 기준으로 연결합니다.
Strong Symbol이 없고 여러 개의 Weak Symbol이 있을 경우, 그중 하나를 선택합니다.
Relocation
Relocation은 두 단계로 이루어집니다.
1. Symbol Resolution 이후, 심볼과 코드가 실제 메모리 주소에 맞게 배치되도록 하는 작업입니다.
2. Relocation을 통해 객체 파일이 메모리에서 실행할 준비를 완료합니다.
Linker의 Symbol Resolution Rules
링커는 여러 객체 파일(.o)을 연결하여 하나의 실행 파일을 생성할 때, 각 객체 파일에 포함된 심볼(symbol)을 해석하고 연결합니다. 이때, 심볼은 Strong Symbol과 Weak Symbol로 분류되며, 다음과 같은 규칙이 적용됩니다.
1. Strong Symbol은 하나만 존재해야 한다
- Strong Symbol은 특정 함수나 변수가 반드시 하나만 정의되어야 하는 것을 의미합니다. 동일한 이름의 Strong Symbol이 여러 개 존재하면 링크 에러가 발생합니다.
2. Weak Symbol은 중복을 허용
- Weak Symbol은 동일한 이름으로 여러 개 존재할 수 있으며, 중복될 경우 우선순위에 따라 연결이 결정됩니다.
- 동일한 이름의 Strong Symbol이 있으면 Strong Symbol을 기준으로 연결되고, 없으면 여러 개의 Weak Symbol 중 하나를 선택하여 연결합니다. 이러한 Symbol Resolution이 완료되면 각 심볼의 주소가 정해지며, 코드와 데이터를 메모리에 배치할 준비가 됩니다.
프로그램 로드와 메모리 배치
프로그램은 실행 시 코드와 데이터가 메모리에 배치됩니다. 보통 text 영역에 명령어가 저장되고, data 영역에는 정적 변수가 저장됩니다. 프로그램이 메모리로 로드될 때 다음과 같은 과정이 이루어집니다.
프로그램을 실행하면 OS가 로더(Loader)를 호출하여 메모리에 배치
프로그램 아이콘을 더블 클릭하면 OS가 해당 프로그램을 메모리에 로드하며, 하나의 프로세스로 할당됩니다. 이때, 프로그램은 가상 메모리 상에 배치되며, 필요한 코드와 데이터가 메모리 맵에 맞춰 할당됩니다.
메모리 할당 방식
일반적으로 메모리 할당은 위에서 아래로 쌓이는 방식으로 진행됩니다. 이는 가상 메모리의 주소가 높은 곳부터 낮은 방향으로 할당되기 때문입니다.
라이브러리 종류
링커는 프로그램에서 사용하는 다양한 기능을 라이브러리에서 가져옵니다. 라이브러리는 미리 컴파일된 객체 파일의 집합으로, 링커의 인풋으로 사용됩니다. 주로 두 가지 종류가 있습니다.
Static Library - 실행 파일에 필요한 코드가 통합되어 함께 저장되므로, 실행 파일 크기가 커지지만 독립적으로 실행 가능합니다.
Dynamic Library - 실행 시 필요한 라이브러리 파일이 메모리에 로드됩니다. 실행 파일의 크기는 줄어들지만, 실행 시점에 외부 라이브러리 파일이 필요합니다.
라이브러리의 목적은 코드의 재사용성을 높이고, 개발자가 일일이 모든 기능을 작성하지 않아도 사용할 수 있도록 필요한 함수만 추출하여 링커가 연결할 수 있게 해주는 것입니다.
ELF와 Executable 파일 구조 ELF 파일
기타 질문에 대한 설명
http://www.kocw.net/home/cview.do?lid=8b9f14bcce404381
컴퓨터구조
컴퓨터의 구성 요소인 프로세서와 메모리, 입출력 장치의 동작원리와 내부 구조에 대하여 학습한다.
www.kocw.net
'독서 > 컴퓨터구조' 카테고리의 다른 글
Pipeline (2) | 2024.11.05 |
---|---|
Computer Arithmetic (0) | 2024.11.05 |
Instruction Set Architecture (1) | 2024.10.25 |