링커(Linker)는 여러 오브젝트 파일을 합쳐 실행 파일을 만들고, 로더(Loader)는 실행 파일을 메모리에 올려 프로세스를 시작한다. 정적 링킹과 동적 링킹의 차이가 성능과 메모리 사용에 큰 영향을 미친다.
컴파일→실행 파이프라인
소스.c → [전처리기] → 소스.i
→ [컴파일러] → 어셈블리.s
→ [어셈블러] → 오브젝트.o
→ [링커] → 실행파일
→ [로더] → 프로세스 (메모리에 적재)
정적 링킹 vs 동적 링킹
정적 링킹 (gcc -static):
- 라이브러리 코드를 실행파일에 포함
- 장점: 배포 단순, 빠른 실행
- 단점: 파일 크기 큼, 라이브러리 업데이트 불가
동적 링킹 (기본):
- 실행 시 .so/.dll 파일 참조
- 장점: 파일 크기 작음, 메모리 공유, 핫픽스 가능
- 단점: 의존성 관리 필요 (DLL Hell)
링커 작업
1. 심볼 해석 (Symbol Resolution):
- 각 .o 파일의 미정의 심볼 → 다른 .o나 라이브러리에서 찾기
2. 재배치 (Relocation):
- 각 섹션의 최종 메모리 주소 결정
- 상대 주소 → 절대 주소 변환
3. 섹션 병합:
- 모든 .text 섹션 합치기
- 모든 .data 섹션 합치기
로더 작업
bash
# 동적 링커 (ld.so) 동작 확인
LD_DEBUG=all ./program 2>&1 | head -30
# 런타임 라이브러리 경로
export LD_LIBRARY_PATH=/custom/lib
관련 개념