目錄
- 參考
- 概述
- 函數(shù)說明
- 示例
1. 參考
- [1] linux.die.net/man/3/dlopen
- [2] test1280/C/C++:使用dlopen求摇、dlsym享幽、dlclose運行時裝載動態(tài)庫
- [3] 燭秋/Linux共享對象之編譯參數(shù)fPIC
2. 概述
- dlopen()函數(shù)以指定模式打開指定的動態(tài)連接庫文件,并返回一個句柄給調(diào)用進程干奢。
- 使用dlsym()通過動態(tài)鏈接庫操作句柄與符號,返回符號對應的地址庐舟。
- 使用dlclose()來卸載打開的庫猪半。
動態(tài)庫編譯
- 編譯選項:
-
-fPIC
:PIC(Position Independent Code)表明使用地址無關代碼,詳細說明見[3]在旱。
-
dlopen使用
- 頭文件:
#include<dlfcn.h>
- 編譯選項:編譯時候要加入
-ldl
(指定dl庫)
3. 函數(shù)說明
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
- dlopen以指定模式打開指定的動態(tài)連接庫文件摇零,并返回一個句柄給調(diào)用進程。dlopen打開模式如下:
- RTLD_LAZY:執(zhí)行延遲綁定桶蝎。只在執(zhí)行引用符號的代碼時解析符號驻仅。如果符號從未被引用,那么它將永遠不會被解析登渣。(延遲綁定只對函數(shù)引用執(zhí)行;對變量的引用總是在加載庫時立即綁定噪服。)
- RTLD_NOW:如果指定了這個值,或者將環(huán)境變量LD_BIND_NOW設置為非空字符串胜茧,則在dlopen()返回之前解析庫中所有未定義的符號粘优。如果不能這樣做,將返回一個錯誤呻顽。
- dlerror返回出現(xiàn)的錯誤雹顺。
- dlsym通過句柄和連接符名稱獲取函數(shù)名或者變量名
- dlclose卸載打開的庫。
4. 示例
count.h
#ifndef _COUNT_H
#define _COUNT_H
int count;
int get();
void inc();
#endif
count.c
#include "count.h"
int get() {
return count;
}
void inc() {
count++;
}
編譯動態(tài)庫:$ gcc -fPIC -shared -o count.so count.c
dlopen/dlsym/dlclose使用示例:
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define NUM 6
#define LIBPATH ""
typedef void (*inc_func)();
typedef int (*get_func)();
const static char *exe_name = NULL;
void usage() {
printf("Usage: %s <lib_path>\n", exe_name);
exit(1);
}
int main(int argc, char **argv) {
exe_name = argv[0];
if (argc < 2)
usage();
const char *libpath = argv[1];
printf("libpath=%s\n", libpath);
void *handler = dlopen(libpath, RTLD_LAZY);
if (handler == NULL) {
printf("ERROR:%s:dlopen\n", dlerror());
return -1;
}
inc_func inc = (inc_func) dlsym(handler, "inc");
if (inc == NULL) {
printf("ERROR:%s:dlsym\n", dlerror());
return -1;
}
get_func get = (get_func) dlsym(handler, "get");
if (get == NULL) {
printf("ERROR:%s:dlsym\n", dlerror());
return -1;
}
for (int i = 0; i < NUM; i++)
inc();
printf("get() return %d\n", get());
dlclose(handler);
return 0;
}
編譯:$ gcc -o main main.c -ldl
運行:$ ./main ./count.so
結(jié)果:
libpath=./count.so
get() return 6