8. 동적 링킹: 공유 라이브러리

위의 정적 라이브러리는 몇가지 중요한 단점들을 지니고 있다; 예로, printf나 scanf와 같은 함수들을 고려해보자. 이러한 함수들은 거의 모든 응용 프로그램에서 사용된다. 만약 시스템이 50~100개의 프로세스를 동작시키고 있다면, 각 프로세스는 각각 printf와 scanf의 실행 가능한 코드의 복사본을 가지고 동작하게 된다. 이것은 메모리 공간의 중대한 낭비를 초래한다. 공유 라이브러리는 이러한 정적 라이브러리의 단점을 해결한다. 공유 라이브러리는 런-타임때 메모리의 임의의 위치로 로드될 수 있는 오브젝트 모듈이다. 그리고 그것은 메모리에서 프로그램과 링킹될 수 있다. 공유 라이브러리는 종종 공유 오브젝트라고도 불리운다. 대부분의 유닉스 시스템에서는 .so로 공유 라이브러리 파일명이 끝나며; HP-UX에서는 .sl로 끝나고 마이크로 소프트사는 DLL(dynamic link libraries)로 부른다.

공유 오브젝트를 만들기 위해, 컴파일러는 다음과 같은 옵션을 가지고 호출된다.

gcc -shared -fPIC -o libfoo.so a.o b.o

위의 명령어는 컴파일러가 a.o, b.o라는 두 개의 오브젝트 모듈들로부터 libfoo.so라는 공유 라이브러리를 만들도록 한다. -fPIC 옵션은 컴파일러에게 위치 독립적인 코드(position independent code)를 만들도록 한다.

만약 bar.o라는 오브젝트 모듈이 a.o, b.o와 의존성이 존재한다고 가정하면, 링커는 다음처럼 불리워진다.

gcc bar.o ./libfoo.so

이 명령어는 로드-타임때 링크될 수 있는 a.out이라는 실행파일을 만든다. 여기서 a.out은 정적 라이브러리를 사용할 때는 포함되었던 a.o와 b.o 오브젝트 모듈을 포함하고 있지 않다. 이 실행파일은 런-타임때 libfoo.so와 함께 해석될 수 있는 재배치와 심볼 테이블만을 포함하고 있다. 따라서, a.out은 libfoo.so와의 의존성이 존재하는 부분적으로 실행가능한 파일(partially executable file)이다. 이 실행가능한 파일은 .interp라는 섹션을 가지고 있는데, 이 섹션은 동적링커(dynamic linker)의 이름을 가리키고 있다. 동적링커 자체도 리눅스에서는 ld-linux.so라는 공유 오브젝트이다. 그래서 실행파일이 메모리로 적재될 때, 로더는 제어권을 동적링커로 넘긴다. 동적링커는 공유 라이브러리들과 해당 프로그램의 주소공간을 매핑시킬 수 있는 start-up 코드를 가지고 있고 다음과 같이 동작한다.

마지막으로, 동적링커는 제어권을 응용프로그램으로 넘긴다. 이때부터 공유 오브젝트는 메모리에 고정되게 된다.