2015. 3. 4.

정적라이브러리와 동적(공유)라이브러리

 라이브러리와 목적파일, 링커에 대해 간단하게 정리를 해보겠다.
먼저 <그림1>과 같은 간단한 .c파일을 생각해보자. main.c에서는 외부함수 swap을 사용하였고 swap.c에서는 외부변수 buf를 사용하였다. 
서로 연관되어 있는 상태이다.

<그림1>





우선 정적 라이브러리, 링킹에 대해서 정리하겠다.

<<정적 링킹>>

<그림2>


gcc -02 -g -o p main.c swap.c 


 <그림2> 와 같이 위 명령어입력하여 실행가능 목적파일 p를 생성한다.
(여기서 -02는 최적화 옵션, -g는 디버깅옵션이다.)


목적파일 p가 만들어지는 자세한 순서는 다음과 같다.

1. 드라이버가 C전처리기(cpp)를 돌려서 C소스파일 main.c를 ASCII 중간파일인 main.i로 번역
2. 드라이버가 C컴파일러(cc1)을 돌려서 main.i를 ASCI 어셈블리 언어파일인 main.s로 번역
3. 드라이버가 어셈블러(as)를 돌려서 main.s를 재배치 가능한 목적파일인 main.o로 번역
4. swap.c에 대해서도 같은 일 반복하여 swap.o 생성
5. 마지막으로 링커 프로그램 ld를 실행하여 실행가능 목적파일 p를 생성하기 위해 main.oswap.o를 연결





<<정적 라이브러리 생성>>

<그림3>

 각각의 목적파일들을 하나의 아카이브로 즉 라이브러리로 만들기 위해 ar도구를 사용한다. 아카이브 파일이름은 .a 접미어로 나타낸다. 
<그림3>에서는 libc.a 라는 정적 라이브러리를 만들었다. 그림이 상세한 내용을 보면 약간 다르긴 하지만 맥락만 이해하면 된다.




<그림4>


gcc -o libvector.a addvec.o multvec.o


(위의 명령어를 사용하여 addvec.o와 multvec.o를 libvector.a로 만들었다.)


<그림3>과 같은 방법으로 만든 라이브러리와 링킹을 하는 과정이 <그림4>에 나와있다. addvec.o와 multvec.o를 가지고 만든 정적 라이브러리 libvector.a와 main2.o와 vector.h로 만든 재배치가능 목적파일 main2.o를 가지고 링커가 p2라는 실행가능 목적파일로 만들고 있다. 이때 중요한 것은 libvector.a에 가지고 있는 모든 목적파일(모듈)을 복사하는 것이 아니라 main2.o에서 쓰여지고 있는 목적파일만 정적 라이브러리에서 복사하게 된다. libc.a에서도 마찬가지로 쓰여진 printf.o만 복사가 된다.

 즉 라이브러리에 있는 모든 목적파일을 복사하는 것이 아니라 라이브러리에 있는 각각의 목적파일에서 정의된 심볼이 main에서 참조되는지 확인하여 참조되는 모듈만 복사하게 된다.


 그러나 정적 라이브러리는 단점이 하나 있다. 만약 라이브러리의 내용이 수정된다면 다시 링크를 해야한다. 따라서 동적 라이브러리가 나오게 되었다.





 <<동적 링크와 라이브러리>>

<그림5>

 동적링크를 하기전에 일단 동적(공유)라이브러리를 만들어야 한다.
<그림4>에서 쓰인 libvector.a는 정적 라이브러리었는데 정적 라이브러리가 아니라 동적 라이브러리로 만들어보자. 아래의 명령어를 입력하여 만든다.


gcc -shared -fPIC -o libvector.so addvec.c multvec.c

(-shared 플래그는 링커가 공유 목적파일을 생성하도록 하는 옵션, -fPIC 플래그는 컴파일러가 위치-독립성 코드를 생성하도록 지시)


라이브러리가 생성되었으므로 이제 링크를 한다.

gcc -o p2 main2.c ./libvector.so

실행가능 목적파일 p2를 '런타임'에 libvector.so 와 링크될 수 있는 형태로 생성한다.
libvector.so로부터의 코드아 데이터 섹션들 중 실제로 p2 실행파일로 복사된 것은 아무것도 없다. 그렇기 때문에 라이브러리가 수정되어도 다시 링크를 할 필요가 없다.

동적링킹은 소프트웨어의 배포, 공성능 웹서버의 개발 등에 적용된다.



위치-독립성 코드 :
  공유 라이브러리를 사용하는 주목적은 다수의 실행되고 있는 프로세스들이 메모리 내에서 동일한 라이브러리 코드를 공유하도록 하는 것이며, 그래서 귀중한 메모리 자원을 절약하는 것이다. 다수의 프로세스들이 하나의 프로그램 사본을 공유하는 방법중에 좋은 접근 방법으로, 라이브러리 코드를 컴파일해서 링커가 수정하지 않고도 어떤 주소에서라도 로드될 수 있고, 실행될 수 있도록 하는 것이다. 이러한 코드는 위치-독립성 코드(PIC)라고 알려져 있다.

출처 :
COMPUTER SYSTEMS A Programmer's Perspective (2nd) (컴퓨터시스템) - DAVID R. O'HALLARON

댓글 1개:

Unknown :

감사합니다