sliver__

[Static and Shared Library] - Shared Library / ldd 명령어 본문

CS/UNIX

[Static and Shared Library] - Shared Library / ldd 명령어

sliver__ 2022. 10. 22. 01:33
728x90

[Static Library의 한계]

  • 여러 유저가 동일한 static library를 링킹하여 executable file을 생성하면 많은 양의 메모리를 사용한다.
  • shared library는 시스템의 여러 프로그램 인스턴스에서 단일 코드 복사본을 공유할 수 있는 메커니즘을 제공한다.

 

[Creating Shared Library]

$ cc -o libshared.so import.o getuid.o -shared
  • gcc command에서 -shared 옵션을 주어 생성할 수 있다.
  • .so는 shared library를 의미한다.

 

[Linking with a Shared Library]

$ gcc main.o -o getuid -L. -lshared -lstdc++
  • -L 옵션은 shared libarary의 경로를 나타내는 옵션이다.
  • -l 옵션은 library의 이름을 알려주는 옵션이다.
  • linker는 shared library에 필요한 method가 있다는 것을 알기 때문에 final executable file에 메모하고, 프로그램이 실행될 때 공유 라이브러리가 로드 되도록 한다.

 

[Choosing Static or Dynamic Libraries]

  • 두 가지 library 들을 사용할 수 있다면, gcc는 보통 shared library를 선택한다.
  • 하지만 -static option을 주면 gcc는 가능하면 static library로 사용한다.

 

[Listing Shared Library References]

$ ldd ./getuid
./getuid:
        libshared.so => not found (0x0)
        libstdc++.so.2 => /usr/lib/libstdc++.so.2 (0x28063000)
        libc.so.3 => /usr/lib/libc.so.3 (0x2809a000)
        libm.so.2 => /usr/lib/libm.so.2 (0x2811b000)
$
  • executable file이 참조하고 있는 shared library를 확인할 수 있다.
  • ldd가 libshared.so 의 위치를 참조할 수 없다고 나온다.
$ ./getuid
/usr/libexec/ld-elf.so.1: Shared object "libshared.so" not found
$
  • getuid 파일을 실행시키면 libshared.so를 찾을 수 없다고 나온다.
  • 왜지...?

 

[The Dynamic Loader]

  • Shared libraries들을 static libraries보다 더 많은 주를 기울여야 한다.
  • Shared libraries들은 on demand로 찾고 load 되기 때문이다.
  • Dynamic loader는 다른 Shared library 로딩 및 dynamic linking시 사용된다.

 

[Searching for Shared Libraries]

  • runtime에 shared library를 로드하려면 dynamic loader가 runtime에 찾아야할 위치를 알아햐 한다.
  • Free BSD와 Linux는 둘 다 라이브러리를 찾을 수 있는 위치를 나타내는 cache 파일을 공유한다.
FreeBSD a.out cache /var/run/ld.so.hints
FreeBSD ELF cache /var/run/ld-elf.so.hints
Linux cache /etc/ld.so.cache
  • 위 cache 파일을 ldconfig 명령어에 의해 업데이트 된다.
  • FreeBSD 와 Linux는 custom library 위치를 지정하는 환경 변수가 존재한다.
Enviroment Variable UNIX Platforms
LD_LIBRARY_PATH Linux, FreeBSD
LIBPATH AIX
SHLIB_PATH HPUX

 

 

$ LD_LIBRARY_PATH=$PWD
$ export LD_LIBRARY_PATH
$ ldd ./getuid
./getuid:
        libshared.so => /home/me/myproject/libshared.so (0x28063000)
        libstdc++.so.2 => /usr/lib/libstdc++.so.2 (0x28065000)
        libc.so.3 => /usr/lib/libc.so.3 (0x2809c000)
        libm.so.2 => /usr/lib/libm.so.2 (0x2811d000)
$
  • 현재 디렉토리 위치를 LD_LIBRARY_PATH 경로로 지정하여 ldd를 실행시키면 dynamic loader가 libshared.so를 찾는 것을 확인할 수 있다.

 

[독립적인 위치 코드]

  • 공유 라이브러리가 여러 프로그램과 코드를 효과적으로 공유하려면 위치 독립적인 코드 형식으로 컴파일해야 한다.
  • 프로그램이 위치 독립적인 코드 형식으로 컴파일되면 시작 주소에 관계없이 모든 메모리 위치에서 실행할 수 있다.
  • 이를 통해 동일한 물리적 메모리 세그먼트를 참조하는 각 프로세스의 서로 다른 상대 위치에서 가상으로 공유할 수 있다.
  • 그림 13.3은 동일한 공유 라이브러리를 호출하는 두 개의 프로그램인 Program_A와 Program_B를 보여준다.
  • 메모리 이미지의 음영 영역은 주소 공간에서 공유 코드가 나타나는 위치를 나타낸다.
  • Program_A의 공유 라이브러리 코드는 Program_B의 공유 라이브러리 코드보다 낮다.
  • 이 코드의 물리적 복사본은 UNIX 커널에 의해 관리되는 시스템의 물리적 메모리에 하나만 존재한다.
  • 음영 처리된 영역은 두 프로세스에서 동일한 공유 코드의 가상 메모리 매핑을 나타낸다.
  • 그림 13.3과 같이 공유 라이브러리 코드를 실행하려면 코드를 위치 독립적인 코드로 컴파일해야 한다.
  • 이것이 완료되지 않으면 동적 로더는 시작 주소가 다른 동일한 라이브러리의 여러 복사본을 메모리에 만들어야 한다.
  • 모듈을 위치 독립적인 코드로 컴파일하려면 FreeBSD 및 Linux에서 gcc(1) 컴파일 옵션 -fPIC를 사용할 수 있습니다.
  • 이 명령은 주어진 모듈을 공유 라이브러리로 만들 수 있는 위치 독립적인 코드로 컴파일한다.

 

[Controlling What Is Shared]

  • UNIX 공유 라이브러리를 만들 때 라이브러리 사용자가 외부에서 볼 수 있는 것을 제어해야 한다.
  • 기본적으로 실행 파일의 일반적인 의미에서 외부에 남아 있는 모든 것은 공유 라이브러리 사용자에게도 외부적으로 표시된다.
  • 라이브러리 내부에 함수가 있는 경우 가능한 한 정적 함수로 정의하는 것이 좋다. 이렇게 하면 비공개로 유지된다.
  • 마찬가지로 불필요한 전역 변수나 공통 저장소를 사용하지 않는 것이 좋다. 공유 라이브러리에서도 볼 수 있다.
  • 이 영역의 엉성함으로 인해 프로그램은 일반 대중에게 공개하지 않으려는 공유 라이브러리의 함수 또는 전역 변수를 호출할 수 있다.
728x90
Comments