위의 정적 라이브러리는 몇가지 중요한 단점들을 지니고 있다; 예로, 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 코드를 가지고 있고 다음과 같이 동작한다.
libfoo.so의 코드와 데이터를 메모리 속으로 재배치한다.
a.out에 있는 참조들을 libfoo.so에 정의되어 있는 것으로 재배치한다.
마지막으로, 동적링커는 제어권을 응용프로그램으로 넘긴다. 이때부터 공유 오브젝트는 메모리에 고정되게 된다.