DLOPEN(3)

명칭
dlopen, dlsym, dlerror, dlclose - 동적 링커에의 프로그램의 인터페이스

프로그램 라이브러리
libc

서식
<dlfcn.h> void * dlopen(const char *path, int mode) void * dlsym(void *handle, const char *symbol) const char * dlerror(void) int dlclose(void *handle)

해설
이러한 함수는, 동적 링커 서비스에 대한 단순한 프로그램의 인터페이스를 제공합니다. 프로그램의 address 공간에 새로운 공유 오브젝트를 추가하는 조작, 공유 오브젝트가 정의하는 심볼의 주소 결합을 취득하는 조작, 및 공유 오브젝트를 사용할 필요가 없어졌을 때에 그것을 제거하는 조작이 제공되고 있습니다.

dlopen() (은)는, path 안의 공유 오브젝트에의 액세스를 제공해, dlsym() (와)과 dlclose() 의 호출에 대해, 오브젝트를 다음에 참조하기 위해서 사용 가능한 기술자를 돌려줍니다. dlopen() (을)를 호출하기 전에 path 하지만 address 공간내에 없었던 경우는 address 공간에 배치됩니다. 이 방법으로, 오브젝트가 처음으로 address 공간에 로드 될 때, 함수 _init() 하지만 존재하면 그것이 동적 링커에 의해 불려 갑니다. 앞의 dlopen() 호출로 address 공간내에 path 하지만 이미 배치되고 있는 경우, 2 번째는 추가되지 않습니다. 그러나, path 위에서의 dlopen() 조작의 참조 카운트치는 관리됩니다. path (으)로 지정된 것이 NULL 포인터이면, 프로세스의 메인 실행 가능 모듈에의 참조로서 해석됩니다. mode (은)는, 로드 된 오브젝트로부터의 외부 함수에의 참조가, 어떻게 그 참조처와 결합하는지, 그방법을 제어합니다. 이것에는 다음의 값 중 1 개가 포함되지 않으면 안됩니다. 어쩌면, 다음에 말하는 추가 플래그와의 OR 를 취한 값에 되겠지요.

RTLD_LAZY
    외부 함수에의 참조는 각각 함수가 최초로 불려 갈 때 해결됩니다.

RTLD_NOW
    외부 함수에의 참조는 모두 dlopen() 에 의해 즉시 결합됩니다.

RTLD_LAZY (은)는, 효율을 잘 한다고 하는 이유로 일반적으로 바람직합니다. 그러나, dlopen() (을)를 호출하고 있는 동안에 미정도리 심볼을 확실히 발견하기 위해서는 RTLD_NOW 하지만 편리합니다.

다음의 플래그의 1 개를 OR 를 취해 mode 인수안에 포함할 수가 있습니다.

RTLD_GLOBAL
    이 공유 오브젝트로부터 얻을 수 있는 심볼 및 필요하게 되는 오브젝트의 유향비순회 그래프 (DAG)가, 그 외 모든 공유 오브젝트로부터의 미해결의 참조를 해결하기 위해서 이용 가능하게 됩니다.

RTLD_LOCAL
    이 공유 오브젝트로부터 얻을 수 있는 심볼 및 필요하게 되는 오브젝트의 유향비순회 그래프 (DAG)가, 동일한 공유 오브젝트로부터의 미해결의 참조를 해결하기 위해서 이용 가능하게 됩니다. 이쪽이 디폴트의 동작입니다만, 이 플래그를 이용해 명시적으로 지정할 수가 있습니다.

dlopen() (은)는, 처리가 실패하면(자) NULL 포인터를 돌려주어, dlerror() 그리고 문의하고 할 수 있는 에러 상태를 설정합니다.

dlsym() (은)는, symbol 하지만 handle 그리고 식별되는 공유 오브젝트내에서 발생했을 때와 같게, 눌 캐릭터로 종료하는 캐릭터 라인 symbol 그리고 기술된 심볼의 주소 결합을 돌려줍니다. dlopen() 에 의해 address 공간에 추가된 오브젝트에 의해 export 된다 심볼은, dlsym() 호출을 통해서만 액세스 가능합니다. 이러한 심볼은, 오브젝트가 로드 될 때에, 벌써 address 공간에 존재하고 있는 심볼의 정의에 옮겨지는 것에서는 않고, 통상의 동적 링크 참조를 채우기 위해서(때문에) 이용 가능한 물건이기도 하지 않습니다.

dlsym() 하지만 특별한 handle NULL (을)를 사용해 불려 갔을 경우는, 그 핸들은 호출이 되고 있는 실행 파일 혹은 공유 오브젝트에의 참조로서 해석됩니다. 이 때문에, 공유 오브젝트는 자기 자신이 가지는 심볼을 참조할 수 있습니다.

dlsym() 하지만 특별한 handle RTLD_DEFAULT (을)를 사용해 불려 갔을 경우는, 오브젝트가 로드 될 때에 미정도리의 심볼을 해결하기 위해서 사용되는 알고리즘에 따라 심볼을 탐색합니다. 탐색되는 오브젝트는 다음과 같이 쓰여진 차례로 됩니다.

1.  참조하고 있는 오브젝트 자신 (혹은 dlsym() 에의 호출이 되고 있는 오브젝트). 다만, 오브젝트가 ld(1) 에 대해서 -Wsymbolic 옵션을 사용해 링크 되었을 경우.

2.  프로그램의 기동시에 로드 되고 있던 전오브젝트

3.  dlopen() 경유로 로드 된 전오브젝트. 이러한 오브젝트는, 참조를 실시하고 있는 오브젝트도 포함한, 필요하게 되는 오브젝트의 유향비순회 그래프에 존재합니다.

4.  RTLD_GLOBAL 플래그를 mode 인수로 설정해 호출했다 dlopen() 경유로 로드 된 전오브젝트

dlsym() 하지만 특별한 handle RTLD_NEXT (을)를 사용해 불려 갔을 경우, 심볼의 검색은, dlsym() 호출을 발행한 다음에 로드 된 공유 오브젝트에 제한됩니다. 그 때문에, 메인 프로그램으로부터 이 함수가 불려 갔을 경우, 모든 공유 프로그램 라이브러리가 검색됩니다. 이 함수가 공유 프로그램 라이브러리로부터 불려 갔을 경우, 그 공유 프로그램 라이브러리보다 다음에 로드 되는 공유 프로그램 라이브러리 모든 것이 검색됩니다. RTLD_NEXT (은)는 프로그램 라이브러리 함수를 감싸는 나팔을 실장하는데 편리합니다. 예를 들면, 나팔 함수 getpid() (이)가 있는 경우, 함수내에서 dlsym(RTLD_NEXT, "getpid") (을)를 사용하면 “진짜의” getpid() 에 액세스 할 수 있겠지요.

심볼을 찾아낼 수 없었던 경우, dlsym() (은)는 null 포인터를 돌려주어, 에러 상태를 설정합니다. 에러 상태는 dlerror() (을)를 사용해 문의할 수가 있습니다.

dlerror() (은)는, dlopen(), dlsym(), 또는 dlclose() 호출동안에 발생한 마지막 에러를 기술한다 눌 캐릭터로 종료하는 캐릭터 라인을 돌려줍니다. 이러한 에러가 발생하고 있지 않는 경우, dlerror() (은)는 NULL 포인터를 돌려줍니다. dlerror() (을)를 호출할 때마다, 에러 지시가 리셋트 됩니다. 그 때문에, 후의 호출이 앞의 호출의 직후에 오는 것 같은 dlerror() 호출을 실시했을 경우, 후의 호출에서는 반드시 NULL 포인터가 되돌아 옵니다.

dlclose() 하 handle 하지만 참조하는 공유 오브젝트에의 참조를 삭제합니다. 참조 카운트치가 줄여지고 0 이 되면(자), 그 오브젝트는 address 공간으로부터 삭제되고 handle (은)는 무효가 됩니다. 이 방법으로 공유 오브젝트를 제거하기 직전에, _fini() 함수가 이 오브젝트로 정의되고 있는 경우에는 그것을 호출합니다. dlclose() (은)는, 처리가 성공하면(자) 값 0 을 돌려줍니다. 그렇지 않은 경우는 -1 을 돌려주어, 에러 상태를 설정합니다. 에러 상태는 dlerror() 그리고 문의하고 할 수 있습니다.

오브젝트에 고유의 함수 _init() (와)과 _fini() (은)는, 인수없이 불려 가 반환값은 기대되고 있지 않습니다.

주
ELF 실행 가능 파일의 경우, 파일중에서 정의되고 있는 심볼을 dlsym() 그리고 보이도록(듯이) 하려면 ld(1) 에 대해서 -export-dynamic 옵션을 사용해 링크를 실시할 필요가 있습니다.

이전의 실장에서는, C 언어로부터 컴파일 한 오브젝트 코드와 심볼의 호환성을 갖게할 수가 있도록(듯이), 외부 심볼에는 모두 언더 스코아를 선두에 붙일 필요가 있었습니다. 현재에도, C 언어의 컴파일러에 대해서 (비추천입니다만) -aout 옵션을 사용했을 경우에는 들어맞읍니다.

에러
dlopen() (와)과 dlsym() (은)는, 에러가 발생했을 경우에는 NULL 포인터를 돌려줍니다. dlclose() (은)는 처리가 성공하면(자) 0 을 돌려주어, 에러가 발생했을 경우는 -1 을 돌려줍니다. 에러가 검출될 때마다, 에러의 상세를 설명하는 메세지가 dlerror() 호출에 의해 꺼낼 수 있습니다.

관련 항목
ld(1), rtld(1), dladdr(3), link(5)