동적 라이브러리 로드
정적 라이브러리를 로드하는 시점
- object 파일(.o 파일)을 링크할 때
- 정적 라이브러리 로딩 / 정적 링크라고 함
- 실행파일의 크기가 커짐
- 라이브러리가 파일에 같이 끼어있기 때문
- 라이브러리를 추가/제거하거나 기존에 사용되던 라이브러리가 업데이트됐을 경우 다시 프로그램을 컴파일해야 한다는 단점 존재
이러한 정적 링크의 단점을 극복하기 위해?
- shared library라는 형식으로 라이브러리를 제작
- 실행 시점(runtime)에 사용할 라이브러리를 연결하여 사용
- 사용되는 라이브러리의 확장자는 .so (shared object)
- 이후 언급되는 동적 라이브러리는 모두 so 파일 또는 shared object 파일로 통합하여 언급함
0. 준비사항
- 대상 프로그램의 컴파일 시 ‘-ldl’ 옵션을 주어야 함
1. dlopen
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
- 매개변수
- filename : 로드할 동적 라이브러리 파일명
- flag : so 파일을 메모리로 적재하는 방법 또는 시점과 관련된 설정값
- (필수) RTLD_LAZY : shared object에 포함된 함수가 최초 호출되는 시점에 해당 so 파일이 로딩됨. shared object에 포함된 전역변수는 호출과 동시에 생성.
- (필수) RTLD_NOW : dlopen()함수 호출과 동시에 loading
- (이하 옵션, ' | ' 연산으로 필요한 flag 세팅)
- RTLD_GLOBAL : loading한 이 라이브러리를 다른 프로그램에서도 사용
- 이 공유 오브젝트에서 정의하는 심볼들이 이후 적재되는 공유 오브젝트들의 심볼 결정에 쓰일 수 있게 한다...라는데 이게 무슨 말일까?
- RTLD_LOCAL : loading한 이 라이브러리는 이 프로그램에 한해서 사용 (default)
- RTLD_NODELETE: dlclose()시에도 메모리에서 내리지 않는다.
- 이후 dlopen()으로 그 오브젝트를 재적재하는 경우에 오브젝트의 정적 변수들이 다시 초기화되지 않는다.
- RTLD_NOLOAD : dlopen()해서 메모리에 로딩하지 않는다. (라이브러리의 존재 여부 및 오류 체크용)
- filename에 지정된 라이브러리 파일이 존재하는지, 또는 라이브러리 파일이 이미 본 프로그램에 로딩되어 있는지 여부를 확인하기 위해 사용
- 만약 존재하지 않는다면 NULL이 반환되고, 이미 적재되어 있다면 해당 shared object에 대한 object handle을 반환한다.
- RTLD_DEEPBIND: 이 라이브러리에 포함된 함수, 변수 등이 다른 라이브러리에 포함된 같은 이름의 함수, 변수들을 무시하고 우선 순위를 갖는다는 의미
- 반환값
- NULL
- so 파일이 존재하지 않음
- so 파일 로딩에 실패
- NULL 아님
- void* 형태의, shared object에 대한 handle 반환
- so 파일을 정상적으로 로딩
- so 파일이 이미 로딩되었음.
- NULL
- 이후 변화
- 로딩된 shared object의 참조 카운트가 1 증가
void *lib_handle = dlopen(modulePath.c_str(), RTLD_LAZY);
2. dlsym
#include <dlfcn.h>
void *dlsym(void *handle, const char *symbol)
-
매개변수
- handle
- dlopen에서 반환받은 shared object handle
- symbol
- shared object에서 찾고자 하는 함수명 또는 변수명
- handle
-
반환값
- NULL
- symbol이 존재하지 않음
- 에러의 경우 dlerror 함수를 호출하면 에러의 원인 파악 가능
- NULL이 아님
- 해당 symbol과 연관된 주소값이 반환
- 이를 받아서 함수포인터 또는 변수로 저장
- 이후 필요할 때 해당 함수/변수를 호출하여 사용하면 됨
- NULL
int (*getData)() = (int (*)())dlsym(lib_handle, "getLibraryData");
3. dlclose
#include <dlfcn.h>
int dlclose(void *handle)
-
매개변수
- handle
- dlopen에서 반환받은 shared object handle
- handle
-
반환값
- 0 : 정상적으로 close됨
- 그 외의 값 : 에러 발생
- 이 경우 dlerror로 에러 메시지 확인 필요
-
이후 변화
- 로딩된 shared object의 참조 카운트가 1 감소
- 참조 카운트가 0이 되면 메모리에서 삭제
int ret = dlclose(lib_handle);
if ( ret != 0 ) {
// dlerror 호출
}
4. dlerror
#include <dlfcn.h>
char *dlerror(void)
-
매개변수
- 없음
-
반환값
- 마지막 dlerror 호출 이후, dlopen 호출에서 발생한 에러 상황에 대한 사유를 문자열로 반환
- 만약 에러가 발생한 적이 없을 경우 NULL이 반환됨
int ret = dlclose(lib_handle);
if ( ret != 0 ) {
printf("Failed to close shared object : [reason : %s]\n", dlerror());
}
'Develop > Etc' 카테고리의 다른 글
[Eclipse/자동완성] Eclipse에서 ctrl + space로 자동완성이 되지 않을 때 (0) | 2020.11.23 |
---|---|
[CentOS] 고정 IP (static IP) 설정 방법 (0) | 2019.12.27 |