0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux下動態(tài)庫和靜態(tài)庫制作與調(diào)用

嵌入式技術(shù) ? 來源:嵌入式技術(shù) ? 作者:嵌入式技術(shù) ? 2022-08-24 15:03 ? 次閱讀

Linux下動態(tài)庫和靜態(tài)庫制作與調(diào)用

1.動態(tài)庫和靜態(tài)庫簡介

靜態(tài)庫是指在應(yīng)用中,有一些公共代碼需要反復(fù)使用,就把這些代碼編譯為“庫”文件;在鏈接步驟中,連接器將從庫文件取得所需的代碼,復(fù)制到生成的可執(zhí)行文件中。這種庫稱為其特點(diǎn)是可執(zhí)行文件中包含了庫代碼的一份完整拷貝;缺點(diǎn)就是被多次使用就會有多份冗余拷貝。

動態(tài)庫又稱動態(tài)鏈接庫英文為DLL,是指DynamicLinkLibrary 的縮寫形式,DLL是一個包含可由多個程序同時使用的代碼和數(shù)據(jù)的庫,DLL不是可執(zhí)行文件。動態(tài)鏈接提供了一種方法,使進(jìn)程可以調(diào)用不屬于其可執(zhí)行代碼的函數(shù)

靜態(tài)庫:在編譯的時候加載生成目標(biāo)文件,在運(yùn)行時不用加載庫,在運(yùn)行時對庫沒有依賴性。

動態(tài)庫:在目標(biāo)文件運(yùn)行時加載,對庫有依賴性。

?1.1 Linux下動態(tài)庫和靜態(tài)庫命令方式
??動態(tài)庫命名方式:libxxx.so。其中so是shared objecd的縮寫,即可以共享的目標(biāo)文件,lib為庫的固定格式,xxx為庫名稱,.so為動態(tài)庫后綴。
??動態(tài)庫命名方式:libxxx.a xxx靜態(tài)庫名稱。Linux 上的靜態(tài)庫,其實(shí)是目標(biāo)文件的歸檔文件。

?1.2 編譯生成共享庫示例

?命令:gcc -fPIC -shared -o libxxx.so xxx.c
此過程分為編譯和鏈接兩部分,-fPIC是編譯選項(xiàng),PIC表示要生成位置無關(guān)的代碼,這是動態(tài)庫的特性,-shared是鏈接選項(xiàng),告訴gcc生成動態(tài)庫而不是可執(zhí)行文件。
上述命令等同于:
gcc -fPIC -c xxx.c
gcc -shared -o libxxx.so xxx.o
如下代碼為例實(shí)現(xiàn)動態(tài)庫編譯與調(diào)用:

pYYBAGMFzSWABhxDAABqunGIh3g098.png#pic_center
[wbyq@wbyq shared]$ gcc -fPIC -shared -o libmyfile.so ./src/*.c -I./include

??gcc -I ?指定頭文路徑

?1.3 動態(tài)庫調(diào)用

[wbyq@wbyq shared]$ gcc main.c -Iinclude -lmyfile -L./lib

??gcc -L ?指定動態(tài)庫路徑
??gcc -l ?指定動態(tài)庫名字

?1.4 程序運(yùn)行

[wbyq@wbyq shared]$ ./a.out 
./a.out: error while loading shared libraries: libmyfile.so: cannot open shared object file: No such file or directory

??錯誤原因:
??系統(tǒng)動態(tài)庫默認(rèn)搜索路徑: /lib 和 /usr/lib
??解決辦法1:將libmyfile.so 拷貝到/usr/lib或者/lib目錄下。
??解決辦法2:修改系統(tǒng)環(huán)境變量,動態(tài)庫環(huán)境變量:LD_LIBRARY_PATH
??修改環(huán)境變量示例:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/hgfs/ubuntu/shared/lib

??注意:在命令行修改環(huán)境變量只對當(dāng)前終端有效。
??解決辦法2:修改系統(tǒng)啟動文件
??Ubuntu下開機(jī)普通用戶啟動文件:~/.bashrc ~/.profile
??管理員用戶:/.profile
??修改~/.bashrc文件:

poYBAGMFzSaAaj0MAAKWKfbkgFg449.png#pic_center

??同步文件:source ~/.bashrc

2 linux靜態(tài)庫創(chuàng)建與調(diào)用

?2.1 linux靜態(tài)庫的命令規(guī)則

??靜態(tài)庫libxxx.a ? xxx靜態(tài)庫名稱。Linux 上的靜態(tài)庫,其實(shí)是目標(biāo)文件的歸檔文件。

?2.2 linux靜態(tài)庫創(chuàng)建步驟

??(1)編寫源文件,通過gcc -c生成目標(biāo)文件。
??(2)用ar歸檔目標(biāo)文件,生成靜態(tài)庫。
??(3)配合靜態(tài)庫,寫一個使用靜態(tài)庫中函數(shù)的頭文件。
??(4).使用靜態(tài)庫時,在源碼中包含對應(yīng)頭文件,鏈接是記得鏈接自己的庫。

?2.3 生成靜態(tài)庫

[wbyq@wbyq shared]$ ar t ./lib/libmyfile2.a  #查看靜態(tài)庫信息
my_cat.o
my_cp.o
my_du.o
[wbyq@wbyq shared]$ gcc main.c -L./lib -lmyfile2 -o app -Iinclude #調(diào)用靜態(tài)

3.gcc編譯器常用選項(xiàng)

?3.1 gcc基本用法

??使用 gcc編譯器的時候,我們必須給出一系列必要的調(diào)用參數(shù)和文件名稱。 GCC 編譯器的調(diào)用參數(shù)大約有100 多個,這里只介紹其中最基本、最常用的參數(shù)。
??gcc 最基本用法:gcc [參數(shù)] [文件名稱]

3.2 常用參數(shù)

-c 只編譯:不鏈接成為可執(zhí)行文件,編譯器只是由輸入的.c 等源代碼文件生成.o 為后綴的目標(biāo)文件,通常用于編譯不包含主程序的子程序文件。
-o output_filename:確定輸出文件的名稱為 output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項(xiàng), gcc 就給出預(yù)設(shè)的可執(zhí)行文件 a.out。
-g:產(chǎn)生符號調(diào)試工具(GNU 的 gdb)所必要的符號信息,要想對源代碼進(jìn)行調(diào)試,我們就必須加入這個選項(xiàng)。
-O:對程序進(jìn)行優(yōu)化編譯、鏈接,采用這個選項(xiàng),整個源代碼會在編譯、鏈接過程中進(jìn)行優(yōu)化處理,這樣產(chǎn)生的可執(zhí)行文件的執(zhí)行效率可以提高,但是,編譯、鏈接的速度就相應(yīng)地要慢一些。
-O2:比-O 更好的優(yōu)化編譯、鏈接,當(dāng)然整個編譯、鏈接過程會更慢。
-E:僅執(zhí)行編譯預(yù)處理;
-S:將 C 代碼轉(zhuǎn)換為匯編代碼;

3.3 編譯時指定庫文件和頭文件路徑

-L:指定動態(tài)庫路徑(可以指定多個路徑)。
示例: gcc test.c -o app -L/usr/lib -L ./lib
?-I:指定頭文件存放的路徑(可以指定多個路徑)。
示例: gcc test.c -I ./ -I /include
?-l:指定庫名稱(可以指定多個路徑)。
示例: gcc test.c -l my_test -l func

4.linux下采用dlopen調(diào)用動態(tài)庫

4.1 dlopen調(diào)用動態(tài)庫意義

為了使程序方便擴(kuò)展,具備通用性,可以采用插件形式。采用異步事件驅(qū)動模型,保證主程序邏輯不變,將各個業(yè)務(wù)已動態(tài)鏈接庫的形式加載進(jìn)來,這就是所謂的插件。 linux 提供了加載和處理動態(tài)鏈接庫的系統(tǒng)調(diào)用,非常方便。
生成動態(tài)庫:gcc -fPIC -shared libxxx.so -o xxx.c

?4.2 dlopen系列函數(shù)介紹

#include 
void *dlopen(const char *filename, int flags);
函數(shù)功能:打開動態(tài)庫
形參:filename --動態(tài)庫路徑+名字 例:./lib/libmyfile.so
???flags --RTLD_LAZY使用時解析(暫緩解析)
???RTLD_NOW --立刻解析
返回值: handle --成功返回庫引用信息,失敗返回NULL
int dlclose(void *handle);
函數(shù)功能:關(guān)閉動態(tài)庫
形參:handle --dlopen函數(shù)返回值
void *dlsym(void handle, const charsymbol);
函數(shù)功能:符號解析
形參:handle --dlopen函數(shù)返回值
???symbol --要解析的符號
返回值:成功返回符號地址,
????失敗返回NULL
char *dlerror(void); //打印錯誤信息

?4.3函數(shù)解析示例

#include "./include/my_file.h"
#include 
#include 
int main()
{
    int (*p)(const char *);//定義一個函數(shù)指針

    /*打開動態(tài)庫*/
    void *handle=dlopen("./lib/libmyfile.so",RTLD_LAZY);
    if(handle==NULL)
    {
        printf("動態(tài)庫解析失敗%s\n",dlerror());//打印錯誤信息
        return 0;
    }
    /*符號解析*/
    p=dlsym(handle,"my_cat");
    int res=p("main.c");
    printf("res=%d\n",res);

    p=dlsym(handle,"my_du");
    p("main.c");
    //typedef unsigned int u32;
    typedef int (*my_cp)(const char *,const char *);//my_cp表示函數(shù)指針類型
    my_cp test;//定義函數(shù)指針變量
    test=dlsym(handle,"my_cp");
    test("main.c","test.c");

    dlclose(handle);//關(guān)閉動態(tài)庫
}

?4.4變量解析示例

#include "./include/my_file.h"
#include 
#include 
int main()
{
    int (*p)(const char *);//定義一個函數(shù)指針
    /*打開動態(tài)庫*/
    void *handle=dlopen("./lib/libmyfile.so",RTLD_LAZY);
    if(handle==NULL)
    {
        printf("動態(tài)庫解析失敗%s\n",dlerror());//打印錯誤信息
        return 0;
    }
    /*符號解析*/
    p=dlsym(handle,"my_du");
    p("main.c");
    printf("-----------------------------------\n");
    /*解析變量*/
    int *p2;
    p2=dlsym(handle,"data");
    printf("*p2=%d\n",*p2);
    *p2=300;
    p("main.c");
    dlclose(handle);//關(guān)閉動態(tài)庫
}


審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11207

    瀏覽量

    208712
  • 靜態(tài)庫
    +關(guān)注

    關(guān)注

    0

    文章

    21

    瀏覽量

    7418
  • 動態(tài)庫
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    6216
收藏 人收藏

    評論

    相關(guān)推薦

    Linux動態(tài)相關(guān)知識

    Linux 下有動態(tài)和靜態(tài),動態(tài)以.so為擴(kuò)展
    的頭像 發(fā)表于 11-07 09:23 ?549次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>下</b><b class='flag-5'>動態(tài)</b><b class='flag-5'>庫</b>相關(guān)知識

    動態(tài)和靜態(tài)的區(qū)別

    一、什么是本質(zhì)上來說庫是一種可執(zhí)行代碼的二進(jìn)制形式,可以***作系統(tǒng)載入內(nèi)存執(zhí)行。二、的種類linux有兩種:
    發(fā)表于 05-26 17:22

    Linux動態(tài)和靜態(tài)制作及使用

    不必從零開始,我們要做的只是在恰當(dāng)?shù)奈恢?b class='flag-5'>調(diào)用合適的庫函數(shù)去實(shí)現(xiàn)相應(yīng)的功能,充分利用前人的勞動成果,就是“站在巨人的肩膀上”。本文主要簡述Linux
    發(fā)表于 11-18 17:05

    Linux靜態(tài)動態(tài)制作與使用

    什么是靜態(tài)函數(shù)庫?動態(tài)函數(shù)庫又是什么?linux靜態(tài)函數(shù)庫是怎樣創(chuàng)建并使用的?動態(tài)函數(shù)庫是怎樣創(chuàng)建并使用的?
    發(fā)表于 04-26 06:45

    如何制作一個Linux動態(tài)

    以下主要介紹Linux 動態(tài)、靜態(tài)、如何使用已有的動態(tài)
    發(fā)表于 11-04 06:58

    靜態(tài)動態(tài)的使用

    是一種可執(zhí)行的二進(jìn)制文件,是編譯好的代碼。使用可以提高開發(fā)效率。在 Linux 下有靜態(tài)動態(tài)
    發(fā)表于 05-04 14:08

    Linux靜態(tài)動態(tài)(共享)的制作與使用

    Linux靜態(tài)動態(tài)(共享)的
    發(fā)表于 07-09 14:39 ?1143次閱讀

    linux靜態(tài)動態(tài)分析

    的二進(jìn)制是不兼容的。 本文僅限于介紹linux。 2.的種類 linux
    發(fā)表于 11-02 10:12 ?1次下載

    動態(tài)鏈接不為人知的秘密

    Linux 下有動態(tài)和靜態(tài),動態(tài)以.so為擴(kuò)展
    的頭像 發(fā)表于 05-04 14:33 ?3553次閱讀
    <b class='flag-5'>動態(tài)</b>鏈接<b class='flag-5'>庫</b>不為人知的秘密

    Linux靜態(tài)、動態(tài)動態(tài)加載

    的存在極大的提高了C/C++程序的復(fù)用性,但是對于初學(xué)者來說有些難以駕馭,本文從Linux的角度淺談Linux
    發(fā)表于 04-02 14:32 ?749次閱讀

    講解Linux虛擬機(jī)之使用動態(tài)和靜態(tài)

    了解 Linux 如何使用,包括靜態(tài)動態(tài)的差別,有助于你解決依賴問題。
    發(fā)表于 05-06 17:05 ?2147次閱讀
    講解<b class='flag-5'>Linux</b>虛擬機(jī)之使用<b class='flag-5'>動態(tài)</b><b class='flag-5'>庫</b><b class='flag-5'>和靜態(tài)</b><b class='flag-5'>庫</b>

    嵌入式Linux動態(tài)和靜態(tài)使用

    以下主要介紹Linux 動態(tài)、靜態(tài)、如何使用已有的動態(tài)
    發(fā)表于 11-01 16:57 ?1次下載
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>下</b><b class='flag-5'>動態(tài)</b><b class='flag-5'>庫</b><b class='flag-5'>和靜態(tài)</b><b class='flag-5'>庫</b>使用

    Linux開發(fā)_動態(tài)靜態(tài)創(chuàng)建與Makefile規(guī)則

    介紹Linux靜態(tài)、動態(tài)創(chuàng)建方式、完成靜態(tài)
    的頭像 發(fā)表于 09-17 15:41 ?1185次閱讀

    Linux中的靜態(tài)和共享

    是一個二進(jìn)制文件,包含的代碼可被程序調(diào)用。例如標(biāo)準(zhǔn)C、數(shù)學(xué)、線程等等。有源碼,可下載后
    的頭像 發(fā)表于 05-10 09:34 ?985次閱讀

    動態(tài)和靜態(tài)制作步驟

    是一種可執(zhí)行的二進(jìn)制文件,是編譯好的代碼。使用可以提高開發(fā)效率。在 Linux 下有靜態(tài)動態(tài)
    的頭像 發(fā)表于 07-27 11:00 ?767次閱讀