라이브러리 (Library)

주로 소프트웨어를 개발할 때 컴퓨터 프로그램이 사용하는 비휘발성 자원의 모임이다. 여기에는 구성 데이터, 문서, 도움말 자료, 메시지 틀, 미리 작성된 코드, 서브루틴(함수), 클래스, 값, 자료형 사양을 포함할 수 있다.

일반적으로 미리 컴파일된 형태의 오브젝트 코드 (Object Code) 형태로 존재하며, 컴파일 시 링커를 통해 프로그램에 링크되어 라이브러리에서 제공하는 기능을 사용할 수 있다.

라이브러리를 사용하는 이유

  • 코드 재사용
  • 소스 코드가 노출되지 않아 기술 유출을 방지
  • 대형 어플리케이션 개발 시간을 단축

정적 라이브러리 (Static Library)

미리 제작한 라이브러리 함수의 오브젝트 코드를 모아놓은 아카이브이다.

컴파일 시 링크 단계에서 프로그램의 오브젝트 코드와 지정한 정적 라이브러리의 오브젝트 코드를 결합하여 하나의 실행 파일을 생성한다.

라이브러리와 프로그램 소스 코드가 같은 실행 파일 안에 들어있기 때문에 실행 속도가 빠르다는 장점이 있지만,

  • 다른 프로그램이 같은 라이브러리를 사용할 경우 동일한 라이브러리가 메모리 공간을 차지하기 때문에 자원 낭비가 발생하고
  • 라이브러리에 문제가 있어 업데이트를 해야할 경우 실행 파일 전체를 다시 컴파일 해야 한다.

공유 라이브러리 (Shared Library)

공유 라이브러리는 여러 오브젝트 파일을 하나의 거대한 오브젝트 파일로 만들어 이를 공유할 수 있도록 한 것이다.

정적 라이브러리가 실행 파일 안에 포함된 것과 달리 실행 파일 안에 어떤 공유 라이브러리가 필요하다는 내용만 포함된다.

공유 라이브러리를 링크한 실행 파일을 실행할 경우 동적 링커 로더가 필요한 라이브러리를 찾아, 메모리에 적재하며 메모리 맵핑을 통해 프로그램 텍스트 영역에서 메모리에 적재된 공유 라이브러리를 이용할 수 있게 한다.

라이브러리를 다른 프로그램들과 공유하여 사용하게 됨으로써 컴퓨터 자원 특히 메모리를 절약할 수 있으며, 라이브러리를 업데이트 해야할 경우 라이브러리 파일만 바꿔주면 컴파일 필요없이 바로 사용할 수 있다 (대신 프로그램을 재실행해주어야 함)

공유 라이브러리의 문제점

정적 라이브러리의 코드는 실행 파일 내에 위치하기 때문에, 변수와 함수 등이 고정된 메모리 위치를 가지게 된다.

공유 라이브러리는 프로그램 실행 시 프로그램과 다른 메모리 영역에 적재되며, 이를 다른 프로세스들과 공유하게 된다.

프로세스 A가 라이브러리 코드내의 내용을 변경하면 (ex : 변수에 상수를 입력) 메모리 영역이 복사되면서 (Copy on Write) 프로세스 B가 사용하는 라이브러리 공간과 분리된다 (라이브러리를 공유한다지만 코드만 공유할 뿐 변수 값까지 공유하는 것은 아니기 때문).

이렇게 되면 공유 라이브러리의 장점인 메모리 절약이 의미 없어진다.

PIC (position-independent code, 위치 독립 코드)

PIC 옵션은 공유 라이브러리를 절대 주소를 사용하지 않고, 상대 주소를 사용하도록 컴파일한다.

정적 라이브러리를 사용한 프로그램 내부에는 라이브러리 코드의 변수와 함수가 절대 주소 (고정)로 들어가 있다.

이에 비해 PIC 옵션을 사용한 동적 라이브러리는 PLT(Procedure Linkage Table)와 GOT(Global Offset Table)를 이용해 라이브러리 코드 내에서 사용하는 변수나 함수 값까지 공유되지 않게 만든다. 물리 주소 공간에 직접적으로 내용이 바뀌는 것은 없으므로 CoW가 발생하지 않게 된다.

PIC를 사용하게 되면

  • CoW가 발생하지 않기 때문에 메모리 공간을 절약할 수 있고
  • 공유 라이브러리 내에서 프로세스 간에 공유해선 안되는 변수, 함수 등만 분리해서 사용할 수 있다.