공부/Embedded

[Linux] Dynamic Loading

래울 2025. 1. 27. 02:21

동적 라이브러리 사용 이유

- 정적 라이브러리는 컴파일 타임에 실행 바이너리에 포함되어야 하지만, 동적 라이브러리는 실행 파일에 포함되지 않아도 된다.

- 따라서 동적 라이브러리는 앱의 컴파일과 별개로 동작할 수 있고, 앱의 실행 파일에 포함되지 않기 때문에 앱의 초기 실행시에 메모리에 로드될 필요가 없다.

- 따라서 앱 실행 속도나 메모리 사용량을 줄일 수 있다.

 

동적 라이브러리 로드

- shared library라는 형식으로 라이브러리를 제작

- 실행 시점에 사용할 라이브러리를 연결하여 사용

- 라이브러리의 확장자는 . so(shared object), 동적 라이브러리

- 대상 프로그램 컴파일 시 -ldl 옵션를 줘서 컴파일

 

dlfcn.h

#include <dlfcn.h>로 사용

 

void *dlopen(const char *filename, int flag)

filename: 파일명, 로드할 동적 라이브러리 .so 파일

flag: .so 파일을 메모리로 적재하는 방법이나 적재 시점

  - RTLD_LAZY: so에 포함된 함수가 최초 호출되는 시점에 해당 so파일을 로드

  - RTLD_NOW: dlopen() 호출과 동시에 로드

    * | 옵션으로 필요한 flag들을 설정, A | B | ..., RTKD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND

반환값: NULL(실패 시), shared object에 대한 핸들을 반환(성공 시)

 

 

void *dlsym(void *handle, const char *symbol)

handle: shared object에 대한 핸들

symbol: shared object에서 찾고자하는 함수명이나 변수명

반환값: NULL(실패 시), 해당 symbol에 대한 주소 값, 변수 또는 함수 포인터 형태로 반환(성공 시)

 

int dlclose(void *handle)

handle: shared object에 대한 핸들

반환값: 0(성공 시), 그 외(실패 시)

 

char* dlerror(void)

반환 값: 에러에 대한 문자열 반환, 없다면 NULL 반환

 

#include <dlfcn.h>

int main(){
    ~~~
    // 1
    void* handle = dlopen("./lib.so", RTLD_LAZY);
    // 2
    void (*func)() = (void (*)())dlsym(handle, "func_1");
    // 3
    dlclose(handle);
    ~~~
    return 0;
}

 

 

 

 

코드

 

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(dynamic_loading)

add_library(hello SHARED hello.c)

add_executable(main main.c)

target_link_libraries(main PRIVATE dl)

 

hello.c

#include <stdio.h>

void print_hello_world(){
	printf("Hello World !!!\n");
}

 

main.c

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
	void *handle;
	void (*print_hello_world)();

	handle = dlopen("./libhello.so", RTLD_LAZY);
	if(!handle){
		fprintf(stderr, "dlopen error: %s\n", dlerror());
		exit(1);
	}

	*(void **)(&print_hello_world) = dlsym(handle, "print_hello_world");
	if(!print_hello_world){
		fprintf(stderr, "dlsym error: %s\n", dlerror());
		dlclose(handle);
		exit(1);
	}

	print_hello_world();
	dlclose(handle);
	return 0;
}

 

실행결과