Linux下庫的使用(二)

共享庫

共享庫和動態庫就是同一個東西,在linux上叫共享對象庫,文件後綴爲 .so,windows上叫動態加載函數庫, 文件後綴是 .dll。
共享庫只是在調用模塊中嵌入調用的代碼在庫的相對位置的地址,當程序執行時,共享庫的程序一起加載到內存中,當執行調用共享庫中代碼的指令時,條轉到共享庫中執行,執行完畢後在條轉回來
共享庫的優點
佔用空間小,方便更新(共享庫發生變化是,程序不需要再次編譯)
共享庫的缺點
相對於靜態庫執行效率略低。
打包一個簡單的共享庫:
將我之前寫的那個文件打包爲共享庫
’1. 編譯.c文件生成.o文件,這裏的-fpic參數的作用爲生成共享庫時生成與位置無關的代碼:

gcc -c -fpic func_add.c func_mul.c func_sub.c

2.鏈接生成共享庫文件

gcc -shared *.o -o libmymath.so

調用共享庫

1.直接調用共享庫

gcc test.c libmymath.so

2.修改環境變量來調用共享庫
打開~/.bashrc

vi ~/.basrhc

在末尾添加代碼:

export LIBRARY_PATH = $LIBRARY_PATH:/home/zhizhen/my_math/

重新加載配置文件

source ~/.bashrc

編譯時要指定庫名(省略前綴lib和後綴 .so)

 gcc test.c -lmymath

3.添加編譯參數來調用共享庫

gcc test.c -L./ -lmymath

使用共享庫

在使用共享庫時,調用者這是記錄了被調代碼在庫的位置,因此在執行時需要共享庫同時被加載,操作系統會根據LD_LIBRARY_PATH路徑來加載共享庫。我們之前的操作雖然編譯成功了但是由於沒有配置LD_LIBRARY_PATH環境變量,操作系統會找不到我們的共享庫。
添加LD_LIBRARY_PATH
1.打開~/.bashrc

vi ~/.bashrc

2.添加LD_LIBRARY_PATH

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zhizhen/my_math/

3.重新加載配置文件

source ~/.bashrc

4.運行可執行文件

./a.out

動態加載共享庫

需要調用頭文件

#include<dlfcn.h>

可以進行的操作
1.打開共享庫

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

參數1:filename:共享庫名或者庫的路徑(如果爲庫名,則會自動從LIBRARY_PATH中尋找相同的庫名)。
參數2:flag加載方式

  1. RTLD_LAZY:懶加載,即當被使用時才加載
  2. RTLD_NOW:立即加載

返回值:共享庫的句柄,類似於文件指針。用來打開我們想要的共享庫

2.獲取標識符地址並使用

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

參數1:handle:共享庫的句柄
參數2:symbol:標識符的名字
返回值:標識符在共享庫中的位置(地址、可以解應用、或跳轉過去),比如如果標識符在共享庫裏是個變量就進行解引用操作,如果是函數就跳轉過去執行。
3.卸載共享庫

int dclose(void* handle)

參數1:handle:共享庫的句柄
返回值:關閉成功返回0,關閉失敗返回-1
4.獲取錯誤信息

char* dlerror(void)

返回值:錯誤信息
例子

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

int main()
{
	void* handle = dlopen("libmymath.so",RTLD_NOW);
	if(NULL == handle)
	{
		puts(dlerror());
		return -1;
	}
	//定義函數指針
	//由於該標示符在共享庫裏表式的是函數,所以會調用該方法
	//該函數執行的是共享庫裏的相加的方法
	int (*add)(int num1,int num2) = dlsym(handle,"func_add");
	if(add == NULL)
	{
		puts(dlerror());
		return -1;
	}
	printf("%d\n",add(12,10));
	return 0;
}
發佈了45 篇原創文章 · 獲贊 44 · 訪問量 3444
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章