CSAPP(7) - Linking

업데이트:

링킹이란?

  • 여러 코드와 데이터 조각을 하나의 파일로 조합하는 것
  • 컴파일 타임, 로드 타임, 런타임에 수행 가능.

링커는 별도 컴파일을 가능하게 한다. 큰 모놀로식 소스 파일을 구성할 필요가 없다.

1. Compiler Drivers

컴파일러 드라이버는 언어 전처리기, 컴파일러, 어셈블러, 링커를 필요에 따라 호출한다.

GCC 드라이버를 사용하면

  1. C 전처리기(cpp)를 실행하여 소스 파일을 ASCII 중간 파일로 변환
  2. C 컴파일러(cc1)를 실행하여 ASCII 어셈블리언어 파일로 변환
  3. 어셈블러(as)를 실행하여 이진 relocatable 목적 파일로 변환
  4. 링커(ld)를 실행하여 실행가능한 목적 파일 바이너리를 생성

목적 파일을 실행하면 os의 loader가 코드와 데이터를 메모리에 올리고 제어를 프로그램의 시작으로 전달한다.

2. Static Linking

ld와 같은 static linker는 relocatable object file과 인자를 입력으로 받아서 완전히 링크된 executable object file을 출력한다.

목적 파일은 바이트 블록의 집합이다. 이 블록은 프로그램 코드, 프로그램 데이터, 링커와 로더를 위한 자료구조를 포함한다. 링커는 이 블록을 연결하고, 연결된 블락의 런타임 위치를 결정하고, 코드와 데이터 블록의 다양한 위치를 수정한다. 대부분의 일은 컴파일러와 어셈블러가 하는 것이고 링커는 타겟 머신에 대한 최소한의 이해만을 필요로 한다.

3. Object Files

목적 파일은 세 종류가 있다.

  1. Relocatable object file : 이진 코드와 데이터가 있다. 다른 ROF와 컴파일 타임에 합쳐져서 실행 가능한 목적 파일이 된다.
  2. Executable object file : 이진 코드와 데이터가 있다. 직접 메모리로 복사되고 실행된다.
  3. Shared object file : 재배치 가능 목적 파일의 특수한 형태. 로드 타임이나 런타임에 메모리로 적재되어 동적으로 링크된다.

목적 파일들은 특정한 object file format을 따라 구성된다.

6.2. Linking with Static Libraries

실제로 모든 컴파일 시스템은 static library라고 하는 object module들의 패키지를 제공한다. 링커는 응용 프로그램에서 참조된 object module만 라이브러리 내에서 복사한다.

10. Dynamic Linking with Shared Libraries

정적 라이브러리는 단점이 있다.

  • 주기적으로 유지관리되고 업데이트되어야 한다.
    • 업데이트한 라이브러리로 프로그램을 재링크해주어야 한다.
  • 각 프로세스마다 중복된 함수를 사용하게 된다.
    • 메모리 자원 낭비

Shared library는 런타임 혹은 로드 타임에 적재되어 메모리 상에서 링크된다. 이 과정을 dynamic linking이라 한다.

동적 링킹이 끝나면 링커는 애플리케이션에게 제어를 전달한다. 이 시점부터 공유 라이브러리의 위치는 고정되고 프로그램 실행 동안 변경되지 않는다.

15. Summary

링킹은 정적 링커에 의해 컴파일 타임에 수행되거나 동적 링커에 의해 런타임 혹은 로드 타임에 수행될 수 있다. 링커는 목적 파일이라 불리는 이진 파일을 조작한다. 목적 파일은 세 유형으로 나눌 수 있다.

  • 재배치 가능 : 정적 링커에 의해 실행 가능 목적 파일로 조합된다.
  • 실행 가능
  • 공유 : 런타임에 동적 링커에 의해 링크 및 로드된다.

링커의 주요 역할은

  • symbol resolution : 목적 파일의 각 전역 심볼을 특정 목적지로 바운드한다.
  • relocation : 각 심볼의 메모리 주소를 결정하고 해당 객체의 참조를 수정한다.

여러 목적 파일은 하나의 정적 라이브러리로 합쳐질 수 있다. 링커는 다른 객체 모듈의 심볼 참조를 해석하기 위해 라이브러리를 사용한다. 많은 링커들이 심볼 해석을 위해 사용하는 순차 스캔은 링크 타임 에러를 발생시킨다.

로더는 실행 가능 파일의 내용을 메모리로 매핑하고 프로그램을 실행한다. 링커는 또한 부분적으로 링크된 실행 가능 목적 파일을 생성한다. 공유 라이브러리에 루틴과 데이터가 정의되어 있다. 로드 타임에 로더는 부분적으로 링크된 실행 가능 파일을 메모리로 매핑하고, 동적 링커를 호출한다. 동적 링커는 공유 라이브러리를 로드하고 프로그램에 재배치함으로써 링킹 작업을 완료한다.

position-independent code로 컴파일된 공유 라이브러리는 여러 프로세스에 의해 런타임에 공유되고 어디서나 로드될 수 있다. 애플리케이션은 공유 라이브러리내 함수와 데이터에 로드, 링크, 접근하기 위해 런타임에 동적 링커를 사용할 수 있다.

출처

  • https://csapp.cs.cmu.edu/
  • 책 “Computer Systems : A Programmer’s Perspective”

태그:

카테고리:

업데이트:

댓글남기기