Programming/C++

.a와 .so 라이브러리 (Dependency)

며용 2022. 2. 26. 17:50

빌드?

소스 코드 ---[번역 프로그램(compiler/ interpreter)]---> 목적 파일 ---[Linker]---> 실행 파일(모듈)


소스코드 컴파일, 링킹, 실행까지 일련의 과정을 빌드라고 한다.

라이브러리에 의존(dependency)하는 프로그램은 라이브러리가 없으면 동작하지 않음.


Library

: 다른 프로그램들과 링크되기 위하여 존재하는 하나 이상의 서브루틴이나 함수들의 집합 파일


실행 파일에 linking되는 시점에 따라 두가지로 나눠진다.

  • 정적 라이브러리 (Static Library)
  • 동적 라이브러리 (Dynamic/Shared Library)



정적 라이브러리

빌드 시에 라이브러리의 목적 코드를 실행 파일에 복사하여 넣는 라이브러리

시스템 환경이 변해도 어플리케이션엔 아무런 영향이 없고 완성된 어플리케이션을 안정적으로 사용할 수 있다.
하지만 모든 오브젝트 코드를 실행 파일에 내장하기 때문에 메모리에 로드되는 애플리케이션 코드 크기가 커진다.

==> 배포 시에 정적 라이브러리를 함께 배포하지 않아도 됨 (이미 포함되어 있기 때문에)

확장자

  • 리눅스: .a (archive)
  • 윈도우: .lib




동적/공유 라이브러리

동적 링크 (Dynamic Link)
라이브러리 코드를 메모리에 올려두고 각 애플리케이션에서 이를 공유하는 방식

공유 라이브러리는 프로그램 실행 시 라이브러리의 코드와 애플리케이션의 코드가 메모리에 로드되는 시점에 링크된다.
라이브러리를 이용하는 애플리케이션에는 호출할 라이브러리 함수의 정보만 들어있다.
애플리케이션이 실행되어 메모리에 로드된 시점에서야 그 함수가 메모리 어디에 위치해 있는지 알 수 있고, 포인터가 쓰여지면서 함수 호출을 한다.
(목적 파일을 만들 때 프로그램에서 사용하는 모든 라이브러리 모듈을 복사하지 않고 해당 모듈의 주소만을 가지고 있다가 런타임에 실행 파일과 라이브러리가 메모리에 위치될 떄 해당 모듈의 주소라 가서 필요한 것만 들고 오는 방식)

라이브러리 코드를 여러 어플리케이션에서 공유할 수 있기 때문에 메모리를 효율적으로 이용할 수 있다.
하지만 매번 라이브러리의 주소에 접근해야 하기 때문에 오버헤드가 존재해 수행 시간은 정적 라이브러리보다 느리다.

동적 로드 (Dynamic Load)
애플리케이션 실행 시에 읽어들이지 않은 라이브러리를 이용할 수도 있다.


==> 실행 파일 배포시에 반드시 함께 배포되어야함.
파일이 없으면 실행 시 오류가 발생하며 라이브러리 이름이 같아도 버전이 다르다면 역시 오류가 발생할 수 있다.


동적 라이브러리 경로 설정 방법

  • system default 경로
    • ld.so.conf 공유 라이브러리 캐시 (/etc/ld.so/cache) 재생성 필요 (ldconfig)
  • LD_LIBRARY_PATH에 추가
    • export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:[라이브러리 경로]
    • ldd 명령어: 공유 라이브러리 의존성을 출력해줌


(프로그램이 시작될 때, ld.so의 동적 링커를 실행하게 됨)
(동적 라이브러리를 사용하여 컴파일된 프로그램은 스텁(Stub) 루틴이라는 것에 링크되는데)
(스텁 루틴은 실행파일 내에서 실제 공유 라이브러리 대신 자리를 차지하며 실행시 ld.so에 의해 실제 루틴으로 대체됨)


확장자

  • 리눅스: .so
  • 윈도우: .dll





Refer:
https://m.blog.naver.com/kr_dukie27/10175747579
https://ledpear.tistory.com/60
https://coding-chobo.tistory.com/64
https://cafe.daum.net/fedoralinux/3sb2/53