공유 라이브러리

 

정적 라이브러리와 공유 라이브러리

  • 기본적으로 라이브러리는 비슷한 기능을 하나의 파일로 묶어서 해당기능을 재사용 할 수 있게 해주는 설계기법이다.
    • 정적라이브러리는 응용프로그램을 컴파일하고 링킹하는 시점에서 정적으로 결합된다.
    • 공유라이브러리는 응용프로그램을 빌드해서 링킹할 때 공유라이브러리의 어떤 기능을 사용할 것이다라고 표시만 해두고, 응용프로그램과 라이브러리의 결합은 응용프로그램이 실행될 때 이루어 진다.

컴파일이란

  • 사용자가 만든 소스를 기계어인 어셈블리어로 바꿔주는 과정을 말한다.
  • 현재 컴파일러들은 주로 아래와 같은 구조를 가지고 있다.
    • 원시프로그램(cpp) => 컴파일러 => 목적프로그램(obj) => 링커 => 응용프로그램(exe)
  • 간단히 말해 컴파일러는 파싱을 한다고 할 수 있다.

목적프로그램이란?

  • 원시프로그램인 cpp 파일을 컴파일한 프로그램으로 obj라는 확장자를 가지고 있다.
  • 목적파일에는 주로 링커가 해야할 일과 소스로 분할 된다.
    • 링커 : #include의 소스를 링크하여 참조
    • 소스를 기계어로 번역

링커란?

  • 중복되는 헤더 예를 들어 Layer7_1.cpp라는 파일에서 stdio.h와 stdlib.h를 include하고 Layer7_2.cpp에서는 stdio.h와 string.h를 include 하고 있다면 양쪽에서 중복되는 stdio.h를 지우고, 만약 a라는 함수가 stdio.h에 선언이 되어 있다면 stdio.h에서 사용하는 메모리를 참조하도록 하는 메커니즘을 가지고 있다.

컴파일러가 하는 일

#include <stdio.h>

int main(int argc, char argv[]){
	printf("Hello World");
	return 0;
}
  • C Pre Processer(cpp)가 #define, #include 구문 등을 전처리하여 layer7.i 생성
      cpp layer7.c > layer7.i
    
  • C complier가 전처리한 layer7.i 소스를 어셈블리로 컴파일 하여 layer7.s 생성
      gcc -S layer7.i
    
  • Assembler는 layer7.s를 어셈블하여 object (layer7.o) 생성
      as -o layer7.o layer7.s
    
  • linker는 printf등 외부 library에 있는 symbol을 링크해서 최종프로그램 생성(a.out)
  • gcc는 위와 같은 과정을 간편하게 해주는 wrapper 역할을 수행하며, -v 옵션을 통하여 모든 과정을 확인 할 수 있다.
      gcc -v layer7.c
    

공유 라이브러리의 이름들

  • 모든 공유 라이브러리들은 “불리는 이름” 이라 불리는 특별한 이름을 가지고 있다. 그 불리는 이름은 접두사 lib, so가 바뀜에 따라 증가되는 기간과 비전 넘버로 이루어진다.
  • 간단한 예로 파일 포멧이 ELF이면 .so 파일, a.out이면 .sa이다.