• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > Linux靜態庫和動態庫的編寫和使用

    Linux靜態庫和動態庫的編寫和使用

    作者: 時間:2016-10-10 來源:網絡 收藏

    庫從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分庫兩種。

    本文引用地址:http://www.czjhyjcfj.com/article/201610/306050.htm

    1 庫的區別 1.1. 靜態函數庫 (1)靜態函數庫的名字一般是lib[name].a (2)利用靜態函數庫編譯成的文件比較大,因為整個函數庫的所有數據都會被整合進目標代碼中,它的優點是編譯后的執行程序不需要外部的函數庫支持,因為所有使用的函數都已經被編譯進去了。這給它帶來的缺點為如果靜態函數庫改變了,那么你的程序必須重新編譯。 1.2. 函數庫 (1)動態函數庫的名字一般是lib[name].so (2)相對于靜態函數庫,動態函數庫所產生的可執行文件比較小,動態函數庫在編譯的時候 并沒有被編譯進目標代碼中,程序執行到相關函數時才調用該函數庫里的相應函數,因此動態函數庫所產生的可執行文件比較小。由于函數庫沒有被整合進你的 程序,而是程序運行時動態的申請并調用,所以程序的運行環境中必須提供相應的庫。動態函數庫的改變并不影響你的程序,所以動態函數庫的升級比較方便。 (3)linux系統有幾個重要的目錄存放相應的函數庫,如/lib /usr/lib,/usr/local/lib。 2 及使用

    靜態庫的制作所要用到的命令:gcc和ar 命令。

    2.1 靜態庫的步驟為: 2.1.1 創建編輯源代碼文件: pr1.c 和 pr2.c

    pr1.c:

    void print1()

    {

    printf(“This is the first lib src!n”);

    }

    pr2.c

    void print2()

    {

    printf(“This is the second src lib!n”);

    }

    2.1.2 編譯.c 文件

    gcc -O -c pr1.c pr2.c

    2.1.3 鏈接靜態庫 在編譯程序中正確找到庫文件,靜態庫必須按照 lib[name].a 的規則命名,如下例中[name]=pr.

    (1)ar -rsv libpr.a pr1.o pr2.o

    a – pr1.o

    a – pr2.o

    (2) ar t ibpr.a

    pr1.o

    pr2.o

    2.1.4 調用庫函數代碼 main.c

    main.c

    int main()

    {

    print1();

    print2();

    return 0;

    }

    2.1.5 編譯鏈接選項

    -L 及-l 參數放在后面.其中-L 加載庫文件路徑,-l 指明庫文件名字.

    gcc -o main main.c -L./ -lpr

    2.1.6 執行目標程序

    3 動態庫 3.1 設計庫代碼

    pr1.c : int p = 2;

    void print() {

    printf(“This is the first dll src!n”);

    }

    3. 2 生成動態庫

    gcc -O -fpic -shared -o dl.so pr1.c

    4 動態庫的使用 4.1 動態庫的隱式調用

    在編譯調用庫函數代碼時指明動態庫的位置及名字 main.c : int main()

    {

    print();

    return 0;

    }

    gcc -o tdl main.c ./dl.so

    當動態庫的位置或者名字發生改變時, 程序將無法正常運行; 而動態庫取代靜態庫的好處之一則是通過更新動態庫而隨時升級庫的內容.

    4.2 動態庫的顯式調用

    顯式調用動態庫需要四個函數的支持,

    (1)函數 dlopen 打開動態庫,

    (2)函數 dlsym 獲取動態庫中對象基址,

    (3)函數 dlerror 獲取顯式動態庫操作中的錯誤信息,

    (4)函數 doclose 關閉動態庫. main.c :

    int main()

    {

    void *pHandle;

    void (*pFunc)(); // 指向函數的指針

    int *p;

    pHandle = dlopen(“./d1.so”, RTLD_NOW); // 打開動態庫

    if(!pHandle) {

    printf(“Can’t find d1.so n”);

    exit(1);

    }

    pFunc = (void (*)())dlsym(pHandle, “print”); // 獲取庫函數 print 的地址

    if(pFunc)

    { pFunc();

    } else

    { printf(“Can’t find function printn”);

    } p = (int *)dlsym(pHandle, “p”); // 獲取庫變量 p 的地址

    if(p)

    { printf(“p = %dn”, *p);

    } else

    { printf(“Can’t find int pn”);

    } dlclose(pHandle); // 關閉動態庫

    return 0;

    }

    gcc -o tds main.c –ld1 –L. 此 時還不能立即./tds,因為在動態函數庫使用時,會查找/usr/lib、/lib目錄下的動態函數庫,而此時我們生成的庫不在里邊。 解決方法有: (1)最直接最簡單的方法就是把生成的動態鏈接庫放到/usr/lib或/lib中去。 (2) export LDLIBRARYPATH=$(pwd) (3)另外還可以在/etc/ld.so.conf文件里加入我們生成的庫的目錄,然后/sbin/ldconfig。 /etc/ld.so.conf是非常重要的一個目錄,里面存放的是鏈接器和加載器搜索共享庫時要檢查的目錄,默認是從/usr/lib /lib中讀取的,所以想要順利運行,我們也可以把我們庫的目錄加入到這個文件中并執行/sbin/ldconfig 。另外還有個文件需要了解/etc/ld.so.cache,里面保存了常用的動態函數庫,且會先把他們加載到內存中,因為內存的訪問速度遠遠大于硬盤的 訪問速度,這樣可以提高軟件加載動態函數庫的速度了。 5 庫依賴的查看 使用ldd命令來查看執行文件依賴于哪些庫。 該命令用于判斷某個可執行的 binary 檔案含有什么動態函式庫。 ldd [-vdr] [filename] 參數說明: –version  打印ldd的版本號 -v –verbose  打印所有信息,例如包括符號的版本信息 -d –data-relocs  執行符號重部署,并報告缺少的目標對象(只對ELF格式適用) -r –function-relocs  對目標對象和函數執行重新部署,并報告缺少的目標對象和函數(只對ELF格式適用) –help 用法信息。 如果命令行中給定的庫名字包含’/',這個程序的libc5版本將使用它作為庫名字;否則它將在標準位置搜索庫。運行一個當前目錄下的共享庫,加前綴”./”。

    ps:這里介紹的只是關于linux下動態庫和靜態庫的基本知識,只要學就能會。但是個人認為庫的高明之處在其接口設計的合理性和可擴展性,要符合通用的習慣等等,認為 《C語言接口與實現:創建可重用軟件的技術》能夠帶來這方面的更深的見解,當然這需要經驗體會。 個人認為,好的接口除了常見的那些標準外,關鍵也應該讓使用者以最小的代價理解并能最快的服務個人的工作中,在使用過程中逐步的了解自己需要的部分。



    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 惠来县| 长武县| 玉门市| 崇礼县| 巫溪县| 山阳县| 瑞丽市| 原阳县| 安达市| 新宁县| 德清县| 汤原县| 门源| 涞水县| 会理县| 萝北县| 商都县| 开江县| 岱山县| 平阳县| 襄垣县| 永嘉县| 阳山县| 铜川市| 高雄县| 乌拉特中旗| 和平县| 浙江省| 芮城县| 阿拉尔市| 禹城市| 宁阳县| 河北区| 连山| 乐安县| 常山县| 镇康县| 舒兰市| 泰安市| 绵阳市| 孝感市|