動態庫 共享庫Shared Object

2021-06-29 13:47:58 字數 3823 閱讀 6909

動態庫或者稱為共享庫,是共享**的另外一種實現方式。

其特徵是在程式實際執行時,動態地載入所呼叫的函式或變數等符號,這樣可以減小應用程式檔案的尺寸;而且遇到功能公升級或者修復bug時只要更新庫檔案就可以了,不必更新應用程式。

在windows環境中,對應的動態庫常以*.dll檔案形式存在,意為dynamic link library。

在linux環境下,生成動態庫也很簡單:新增編譯選項,直接將*.c編譯成*.so

例如:

gcc -shared s1.c -o so1.so

而使用動態庫檔案時,呼叫函式使用dlopen,dlsym等函式動態載入so檔案,就能獲取其中的符號了。

例一:

我們現在csdn.c檔案中定義乙個函式fry_it和乙個變數data1

int fry_it(int

*n) return0;}

int data1 = 3;

然後我們就可以把這個原始檔製作成so,命令如下:

test@test

:~$ gcc -shared csdn.c -o libcsdn.so

然後我們再來寫乙個應用程式源**main.c,通過訪問這個so來使用其中的函式和變數

#include 

#include

#include

int main()

pf = dlsym(pso, "fry_it");

if(pf)

else

pdata = (int

*) dlsym(pso, "data1");

if(!pdata)

printf("data=%d\n", *pdata);

(*pf)(pdata);

printf("after fried data=%d\n", *pdata);

out:

if(dlclose(pso))

printf("%s return\n", __func__);

return

0;}

必要的,我們需要定義乙個void*型別的指標pso,用來儲存指向開啟的so庫的入口。

在這裡例子中,還定義了函式指標pf和指向變數的指標pdata用來訪問so中的符號。

在成功開啟我們需要的so後,就可以通過pso來搜尋庫中我們需要的符號。符號的意思就是說函式名或者變數名。

把應用程式編譯出來:

test@test

:~$gcc main.c -ldl

test@test

:~$ ./a.out

main begin

fry_it() symbol found

data=3

after fried data=6

main return

例二:

通過例一我們看到了so的製作,使用等基本用法。但是這樣使用so有很致命的缺點:

需要在應用程式中提前預製好藥使用的符號。

例一中只用了簡單的fry_it這乙個函式和data1這乙個變數,萬一將來我們需要增加幾百個函式,或者需要更新fry_it的引數型別怎麼辦?

萬一將來需要增加data2,data3……data100,那麼在應用程式中寫100個dlsym(pso, 「data……嗎?

即使允許可以修改主程式,那麼每改乙個細節都要重新發布一次主程式嗎?如果可以那麼公升級程式前還要解除安裝舊程式嗎?

我們來看例二:

先將so原始檔優化一下

test@test:~$ cat csdn0.c 

#include

#include "csdn.h"

int double_it(int

*n) return0;}

csdn_t csdn = ;

把csdn_t的定義放在另外乙個檔案裡,便於引用:

test@test:~$ cat *.h

typedef

struct csdn_t

csdn_t;

製作so:

test@test

:~$ gcc csdn0.c -shared -o libcsdn0.so

然後我們來看怎麼使用:

test@test:~$ cat main0.c 

#include

#include

#include

#include "csdn.h"

int main()

pc = (csdn_t *)dlsym(pso, "csdn");

if(pc)

else

printf("data=%d\n", pc->data);

pc->fry_it( &pc->data);

printf("after fried data=%d\n", pc->data);

out:

if(dlclose(pso))

printf("%s return\n", __func__);

return

0;}

編譯時記得引用dl這個lib:

test@test

:~$ gcc main0.c -ldl

例三:

類似的我們來看android原始碼中hal是怎麼使用so的:

在android原始碼中,系統程序統通過函式hw_get_module來載入需要的so檔案,其中的load函式如下:

58

/**59 * load the file defined by the variant and if successful

60 * return the dlopen handle and the hmi.

61 * @return 0 = success, !0 = failure.

62 */

63static

int load(const

char *id,

64const

char *path,

65const

struct hw_module_t **phmi)

66 83

84/* get the address of the struct hal_module_info. */

85const

char *sym = hal_module_info_sym_as_str;

86 hmi = (struct hw_module_t *)dlsym(handle, sym);

87if (hmi == null)

9293

/* check that the id matches */

94if (strcmp(id, hmi->id) != 0)

99100 hmi->dso = handle;

101102

/* success */

103 status = 0;

104105 done:

106if (status != 0)

112 } else

116117 *phmi = hmi;

118119

return status;

120 }

**中hal_module_info_sym_as_str就永遠是hmi這個字串,每個被呼叫的模組在hmi這個結構體中定義自己的各種功能。

共享庫 動態庫

動態庫的命名規則 lib 庫的名字 so libmyname.so 動態庫的建立和使用 共享庫 步驟一 生成對應的.o檔案 c o gcc fpic c c i include 生成與位置無關的.o檔案 fpic 與位置無關 步驟二 將生成的.o檔案打包成動態庫.so檔案 gcc shared o ...

靜態庫,共享庫,動態載入庫

一 靜態庫 1.概念 靜態庫就是一些目標檔案的集合,以.a結尾。靜態庫在程式鏈結的時候使用,鏈結器會將程式中使用 到函式的 從庫檔案中拷貝到應用程式中。一旦鏈結完成,在執行程式的時候就不需要靜態庫了。由於每個使用靜態庫的應用程式都需要拷貝所用函式的 所以靜態鏈結的檔案會比較大。2.建立與應用 首先建...

動態鏈結共享庫

靜態庫有一些明顯的缺陷,它與所有的軟體一樣,需要定期維護和更新。如果應用程式設計師想要使用乙個庫的最新版本,他們必須以某種方式了解到該庫的更新情況,然後顯示的將他們的程式與更新了的庫重新鏈結。其次,幾乎每乙個c程式都使用了標準i o函式,執行時這些函式的 會被複製到每個執行程序的文字段中,在執行上百...