Seperate Compile 분할 컴파일이란?
: 하나의 큰 프로젝트를 여러 multiple files로 나누는 것을 의미한다. ( 더 다루기 쉬운 모듈로 쪼갬)
모듈 : 관련된 일들을 수행하는 함수와 데이터의 집합 (리눅스에서는 file 단위_각각의 object 파일을 모듈이라고 보자)
컴파일러 드라이버 동작과정 요약
본격적으로 링커에 대해 알아보기 전, 컴파일러 드라이브의 컴파일 과정을 복기시켜보자 !
//정적 연결 예제
gcc -Og -o prog main.c sum.c
링커는 재배치 가능 목적파일들을(.o) 연결해 실행가능 목적파일 prog를 형성한다.
드라이버는 먼저 C 전처리기를 돌리고, 이것은 C 소스파일 main.c 를 ASCII 중간 파일인 main.i로 번역한다.
다음으로 C 컴파일러(cc1)을 돌려 main.i 를 ASCII 어셈블리 언어 파일인 main.s로 번역한다.
그 다음에 드라이버는 어셈블러를 돌려서(as) main.s를 재배치 가능한 바이너리 목적파일일 인 main.o로 번역한다.
sum.o를 생성하기 위해서도 동일한 과정을 수행한다. 마지막으로 링커 프로그램 ld를 실행하는데, 이것은 실행 가능 목적파일 prog를 생성하기 위해 main.o와 sum.o를 연결한다.
ld -o prog [system object files and args]
최종적으로 실행파일 prog를 실행시키려면, linux 쉘에서 이름을 명령줄에 입력한다.
linux> ./prog
Q. 분할 컴파일이 필요한 이유
→ 모듈성 : 코드의 재사용 허용으로 인해 협업에 용이함.
→ 효율성
1. 시간적 측면 : 분할 컴파일로 하나의 소스파일만 수정, 컴파일, 재링크할 수 있다. 다른 소스파일들은 재컴파일 할 필요가 없다.
2. 공간적 측면 : 많이 쓰이는 함수는 단일의 파일로 병합할 수 있다. 실행가능한 파일들과 실행되고있는 메모리 이미지는 오직 실제로 사용되는 함수를 위한 코드만 포함된다.
즉, 실행 파일 자체는 필요한 함수만 참조하고, 실행할 때 동적으로 필요한 라이브러리를 찾아서 로딩한다. 이로 인해 실행 파일은 작은 크기를 유지할 수 있으며, 메모리 효율성도 높아진다!!!
Q. 라이브러리가 필요한 이유
1. binary functions 은 .o files에 포함된다.
2. 시스템은 수많은 .o files을 포함한다.
수많은 .o files 을 일일이 검사하는 것이 아니라, 그룹화해서 관리한다.
Linking Error 가 생기는 대표적인 경우
- No definition error:
- 참조된 변수나 함수가 정의되지 않았을 때 발생합니다.
- 해결: 변수나 함수의 정의를 추가하거나 올바른 객체 파일을 링킹합니다.
- Multiple definition error:
- 동일한 변수나 함수가 여러 파일에서 정의되었을 때 발생합니다.
- 해결: 변수나 함수의 정의는 한 파일에서만 하고, 다른 파일에서는 extern으로 선언만 합니다.
How. 분할컴파일의 버그를 줄이는 방법
1. 헤더파일 : extern 변수들의 집합
ex) type을 바꾸고 싶다면 , 헤더파일에서 type 수정 → 전처리기가 수정된 부분을 반영할 수 있도록 만든다.
2. 라이브러리 : 자주 사용되는 func 집합
obj 도 결국은 파일 → disk 접근 시 비효율적 → 쪼개서 관리하자!
Define v.s. Declare
Define
- 변수, 함수를 만든다.
- 새로운 메모리 공간을 할당한다.
int x;
int sum (int* a, int n) {...};
Declare
- 컴파일을 위한 정보와 관련된다.
- 새로운 메모리 공간이 할당되지 않는다.
extern int x;
int sum(int *a, int n) ;
Attributes of Variable
Local variable
- scope : block scope
- storage duration : dynamic _ 런타임 때 일시적으로 존재함
- Linkage : X → symbol 또한 아님!!! 함수 내에서만 존재하는 변수임
※ 지역변수가 전역변수보다 우선한다.
Global variable
- scope : file scope 모든 block에서 접근 가능하다!
- storage duration : static _ 실행 시작 시 대부분 data 공간(section) 에 저장됨
- Linkage : external(외부 파일 참조 가능) or internal(파일 내부에서 참조가능)
전역변수의 다중 정의 문제 → 컴파일 오류
해결 1. 하나의 파일은 extern ~ 처리
해결 2. 파일마다 다른 배타적인 전역변수라면 static (internal linkage) 을 활용한다.
Static / Extern Modifier
Static Modifier
static : private to this file → internal linkage
변수/ 함수는 속한 파일 내에서 지역적인 특성을 갖는다.
1. Intenal linkage (전역변수 앞에 있을 때) - 다른 파일에서 참조할 수 없다.
2. Permanent at data section (지역변수 앞에 있을 때) - 영구적으로 값이 유지되며 일시적인 레지스터나 스택에 있지 않고, .data section에 할당된다. → 한 번만 정의된다 !!!
- 다른 함수에서 같은 이름으로 여러번 정의되었을 경우, data section에 x.1 x.2 ~~ 이런 식으로 저장된다.
int f() {
static int x= 10;
return x;
}
int g() {
static int x= 100;
return x;
}
External Modifier
extern : 다른 파일에서 참조가능한 변수/함수를 나타낸다. → external linkage
Variable은 명시적으로 extern 작성이 필요하다. 다만,
Function의 경우 extern을 명시적으로 작성하지 않아도 된다.
Q. Extern / Static modifiers 가 필요한 이유
'Major S-T-U-D-Y > System Programming' 카테고리의 다른 글
[시스템 프로그래밍] 7. (3) 링킹과정 1단계 : 심볼 해석과 재배치 (0) | 2024.11.26 |
---|---|
[시스템 프로그래밍] 7. (2) Linking 정적/동적 링킹 과정과 (0) | 2024.11.22 |
9. Derived type - array, pointer, and structure (1) (1) | 2024.11.12 |
8. Procedure Call and Stack (0) | 2024.11.12 |
GNU make (1) | 2024.10.18 |