동적라이브러리(DLL)은 시스템 자원(디스크 및 메모리 공간)을 절약하고, 프로그램의 유지보수를 쉽게하는 장점이 있다.
여기서는 특정 어플리케이션을 위한 동적라이브러리 작성 및 사용방법에 대해 알아본다.
라이브러리 API 함수는
- "dlopen" : 메모리에 라이브러리를 맵핑하고 핸들을 리턴
- "dlsym" : 함수 포인터를 리턴
- "dlerror" : 오류 문자열 포인터를 리턴, NULL은 정상
- "dlclose" : 핸들을 닫고 맵핑을 해제
동적라이브러리는 "dlopen"에서 절대경로를 설정해서 라이브러리를 지정할 수 있다. 절대 경로가 지정되지 않으면,
- "LD_LIBRARY_PATH" 환경 변수에서 지정된 경로
- "/etc/ld.so.cache"의 라이브러리 리스트
- "/usr/lib"와 "/lib" 경로
에서 라이브러리를 찾게 된다. Shell에서 현재 디렉토리를 "LD_LIBRARY_PATH"에 설정하는 것은
export LD_LIBRARY_PATH=`pwd`
이고, pwd를 인용하는 "`"는 TAB 위에 있는 [~/`]키를 사용해야 한다.
다음의 libhello.c, testdll.c, test_dll.sh 파일로 동적라이브러리 예제를 작성하고 동작을 확인할 수 있다.
libhello.c
#include "stdio.h"
#include "string.h"
int hello(char *msg)
{
printf("%s\n", msg);
return strlen(msg);
}
testdll.c
#include "stdio.h"
#include "string.h"
#include "unistd.h"
#include "dlfcn.h"
#define _MAX_STRING 80
#define _LIB_FILE "libhello.so"
int invoke_method(char *lib, char *method, char *argument)
{
void *dl_handle;
int (*func)(char *);
char *error;
int ret = 0;
/* 공유 목적 파일을 연다. */
dl_handle = dlopen(lib, RTLD_LAZY);
if (!dl_handle)
{
printf("!!! %s\n", dlerror());
return -1;
}
/* 목적 파일에서 심볼(메서드)을 찾는다. */
func = dlsym(dl_handle, method);
error = dlerror();
if (error != NULL)
{
printf("!!! %s\n", error);
return -2;
}
/* 찾아낸 메서드를 호출한다. */
ret = (*func)(argument);
/* 객체를 닫는다. */
dlclose(dl_handle);
return ret;
}
int main(int argc, char *argv[])
{
char lib[_MAX_STRING+1];
char method[] = "hello";
char argument[] = "Hello, library world...";
char pwd[_MAX_STRING+1];
getcwd((char *)pwd, _MAX_STRING);
sprintf(lib, "%s/%s", pwd, _LIB_FILE);
printf("Result: %d\n", invoke_method(lib, method, argument));
}
test_dll.sh
# Build library
if [ -f libhello.o ]; then rm libhello.o
fi
gcc -c -fPIC libhello.c
if [ -f libhello.so ]; then rm libhello.so
fi
gcc -shared -lc -o libhello.so libhello.o
# Build test program
if [ -f testdll.o ]; then rm testdll.o
fi
gcc -o testdll testdll.c -ldl
# Run test program
./testdll
참고 자료:
- 프로그램 라이브러리 하우투
- 리눅스 동적 라이브러리 분석
- Linux 애플리케이션을 위한 DLL 작성하기 (한글)