7.10 Dynamic Linking with Shared Libraries(공유 라이브러리 동적 링크)
정적 라이브러리(static library) 단점
- 정적 라이브러리는 주기적으로 유지 관리하고 업데이트해야 한다.
- 최신 버전 정적 라이브러리를 이용하고 싶으면 프로그래머가 프로그램을 업데이트된 라이브러리를 다시 link 해줘야한다.
- C언어에서 printf, scanf와 같이 표준I/O는 run-time 동안 실행 중인 각 프로세스의 text segement에 복사된다. 이는 수백 개의 프로세스를 실행하는 일반적인 시스템에서 자원의 상당한 낭비를 야기한다.
공유 라이브러리(shared library)
- 공유 라이브러리(shared library)는 정적 라이브러리의 위와 같은 단점을 해결하는 혁신적인 최신 방법이다.
- 공유 라이브러리는 run-time 또는 load-time에 임의의 메모리 주소에 로드되고 메모리의 프로그램에 link될 수 있는 object module이다.
- 위 프로세스는 dynamic linking이라고 불리고 dynamic linker에 의해 수행된다.
- 공유 라이브러리는 shared objects라고도 한다.
- Linux 시스템에서는 접미사 .so로 표시됨
- 윈도우 OS에서는 DLL(Dynamic Link Library)라고 하는 공유 라이브러리를 사용한다.
- 공유 라이브러리는 두 가지 형태로 "shared(공유)" 된다.
- 1. 파일 시스템에는 특정 라이브러리에 대해 정확히 하나의 .so 파일이 있다. 이 .so 파일의 코드와 데이터는 라이브러리를 참조하는 모든 executable object file에서 공유된다.
- 이를 참조하는 실행 파일에 복사 및 포함되는 정적 라이브러리와는 다른 방식.
- 2. 메모리에 있는 공유 라이브러리의 .text 섹션의 단일 복사본을 실행 중인 다른 프로세스에서 공유할 수 있다.
- 이에 대해서는 Chapter 9 가상 메모리에서 알아볼 것.
Dynamic linking 과정
- 위 그림은 그림 7.7의 예제 프로그램에 대한 dynamic linking 과정을 요약한 것이다.
- 1. 벡터 루틴의 공유 라이브러리 libvector.so를 구축하기 위해 컴파일러 및 링커에 대한 아래 지시문과 함께 컴파일러 드라이브를 호출한다.
- linux> gcc -shared -fpic -o libvector.so addvec.c multvec.c
- -fpic 플래그는 컴파일러가 위치 독립적인 코드를 생성하도록 지시한다. (자세한 내용은 다음 섹션에서 다루겠다)
- -shared 플래그는 shared object file를 만들도록 링커에 지시한다.
- 2. 공유 라이브러리를 만들었다면 그림 7.7 예제 프로그램에 링크한다.
- linux> gcc -o prog2l main2.c ./libvector.so
- 위 지시문을 이용하면 libvector.so(공유 라이브러리)와 링크할 수 있는 형식으로 executable object file prog2l이 생성된다.
- 이에 대한 기본 원리는 executable file이 생성될 때 , 일부 링크를 정적으로 수행한 다음 프로그램이 load될 때 동적 링크 과정을 완료하는 것이다.
- 여기서 알아야할 것은 libvector.so의 코드 또는 데이터 section이 실제로 executable object file prog2l에 복사되지 않는다는 것이다. (정적 라이브러리와 다른 점)
- 대신에 링커는 일부 relocation 및 symbol table 정보를 executable object file prog2l에 복사하여 libvector.so의 코드 및 데이터에 대한 참조를 load time에 확인할 수 있도록 한다.
- 3. loader가 실행 가능한 prog2l을 로드하고 실행하면 섹션 7.9에서 설명한 기술을 사용하여 부분적으로 링크된 실행 가능한 prog2l를 로드한다.
- prog2l이 dynamic linker로 경로 이름을 포함하는 .interp 섹션을 포함하고 있는 것을 확인한다.
- .interp 섹션은 그 자체가 공유 객체이다. ex) Linux 시스템의 ld-linux.so)
- 그리고 나서 loader는 dynamic linker를 로드하고 실행한다.
- 6. dynamic linker는 relocation을 수행하여 link 작업을 완료한다.
- libc.so의 텍스트와 데이터를 일부 메모리 segment로 relocation.
- libvector.so의 텍스트와 데이터를 다른 메모리 segment로 relocation
- prog2l의 모든 reference를 libc.so 및 libvector.so에 의해 define된 symbol로 relocation.
- 7. 마지막으로 dynamic linker는 응용 프로그램(application)에 제어를 전달
- 이 시점부터 공유 라이브러리의 위치는 고정되며 프로그램 실행 중 변경되지 않는다.