日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

静态库调用_静态链接和动态链接对比简析

發布時間:2024/10/8 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 静态库调用_静态链接和动态链接对比简析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0. 簡介

在Linux環境下進行開發工作,代碼要經過編譯鏈接生成二進制可執行文件,才能被CPU識別并執行;程序的編譯過程可以參考另外一篇文章《linux程序編譯過程簡析》;鏈接過程分為兩種,靜態鏈接和動態鏈接;

靜態鏈接和動態鏈接最明顯的區別是,兩者鏈接的時機不一樣;靜態鏈接在生成可執行文件時;動態鏈接在程序加載執行時;

1. 靜態鏈接

多個目標文件經過靜態鏈接生成靜態庫,靜態庫也可以看作是多個目標文件的集合;鏈接器在鏈接靜態庫時,是以目標文件為單位的,使用ar命令可以查看靜態庫中包含的目標文件;在引用靜態庫中的printf()函數時,鏈接器會把庫中包含printf()函數實現的目標文件鏈接進去,如果在這個目標文件中還有很多別的函數實現,這些沒有被實際使用到的函數也會被鏈接到結果文件中,所以應該盡量將函數實現按照功能模塊分成多個目標文件,以減少將沒有使用到的函數鏈接到可執行文件中;

靜態鏈接過程分兩步:

  • 空間與地址的分配;掃描所有目標文件,合并相似的段,收集所有的符號信息;
  • 符號解析與重定位;調整代碼位置;
  • 靜態鏈接的優缺點

    缺點

  • 浪費空間,因為每個可執行程序中對多有需要的目標文件都需要一份副本,所以多個程序對同一個目標文件有依賴,同一個目標文件會在內存中存在多個副本;
  • 更新困難,因為庫函數修改后,需要重新進行編譯鏈接生成可執行程序;
  • 優點

    在可執行程序中已經包含了執行程序需要的所有函數,在執行的時候運行速度更快;

    2. 動態鏈接

    動態鏈接的基本思想是把程序按照模塊拆分成相對獨立的部分,在程序運行時將他們鏈接形成完整的程序,而不是像靜態鏈接一樣,把所有程序模塊鏈接到一起生成一個可執行文件;

    動態鏈接在程序運行時才進行鏈接形成完整的程序;程序編譯的鏈接階段,鏈接器只是拷貝了一些重定位和符號信息;在程序加載時才解析so文件中代碼和數據的引用;

    某個程序在運行中要調用某個動態鏈接庫中的函數時,系統會先檢查所有正在運行的程序,內存中是否已有該庫函數的副本,如果有,則將其共享給程序,如果沒有,則鏈接載入需要的動態鏈接庫文件;被調用的動態鏈接庫函數被加載在內存的某個位置,所有調用庫文件的程序都指向這個代碼段,因此庫文件的代碼必須使用相對地址,而不是絕對地址;在編譯時,這些庫文件用來做動態鏈接庫,要用地址無關代碼;

    2.1 動態鏈接過程舉例

    假設有兩個程序demo1.o和demo2.o,都依賴庫文件demolib.o,如果程序demo1.o先運行,系統先把demo1.o加載到內存中,系統檢測到demo1.o中用到了庫文件demolib.o中的函數,系統會加載demolib.o和其他的依賴庫文件到內存中;

    在程序demo2.o運行時,同樣加載demo2.o到內存,之后系統檢測到demo2.o也用到了demolib.o中的函數,此時由于庫文件demolib.o已經加載到內存中了,此時就不需要重新加載demolib.o文件,而是將內存中已經存在的demolib.o映射到demo2.o的虛擬地址空間中進行鏈接,形成可執行程序;

    2.2 動態鏈接的優缺點

    優點

    1. 即使需要每個程序都依賴同一個庫,該庫文件不會像靜態鏈接在內存中存在多分副本,而是多個程序執行時共享同一個庫函數副本;

    2. 更新方便,更新時只需替換庫文件中原來的目標文件,無需將所有的程序重新編譯鏈接;在程序運行時,新版本的目標文件會被加載到內存中并進行鏈接;

    缺點

    由于把鏈接操作推遲到了程序運行時,每次程序運行都需要進行鏈接,性能會有一些損失;

    2.3 動態鏈接地址重定位

    動態鏈接把鏈接過程推遲到了程序運行時,在生成可執行文件時,需要用到動態鏈接庫;即在生成可執行程序時,發現少了一個外部實現的函數,此時會檢查動態鏈接庫,如果檢查到該函數名時一個動態鏈接符號名,可執行程序就不會對這個符號重定位,而把這個過程推遲到程序裝載時進行;

    3. 生成庫文件

    3.1 生成靜態鏈接庫

    源代碼文件:demo.c

    鏈接庫的源代碼文件:testlib.c

    $ gcc -c testlib.c -o testlib.o // 把lib.c文件編譯不鏈接,生成.o文件$ ar testlib.o -rc libtest.a // 使用ar工具把.o文件打包生成.a庫文件

    3.2 靜態鏈接庫的使用

    $ gcc demo.c -o demo -ltest -L. // testlib.a庫在鏈接時使用-ltest

    -L:表示要鏈接的庫所在的目錄

    -l:指定鏈接的庫,編譯器查找鏈接庫時會在名稱前加上lib,后邊加上.a或.so來確定庫名稱;

    3.3 生成動態鏈接庫

    源代碼文件:demo.c

    鏈接庫的源代碼文件:testlib.c

    $ gcc -fPIC -c testlib.c -o testlib.o // 編譯不鏈接$ gcc -shared testlib.o -o libtest.so // 使用-shared生成動態鏈接庫

    -fPIC:用來創建與地址無關的編譯程序,為了在多個程序間共享

    -shared:指定生成動態鏈接庫

    也可以將以上兩步操作合并為一步

    $ gcc -fPIC -shared testlib.c -o libtest.so

    3.4 動態鏈接庫的使用

    $ gcc demo.c -o demo -ltest -L. ? ? // testlib.a庫在鏈接時使用-ltest

    由于動態鏈接庫是在程序加載執行時進行鏈接,所以在系統加載可執行程序時,需要庫文件的名字和絕對路徑,還需要系統提供的動態加載器;對于ELF格式的可執行文件,動態加載器是ld-linux.so*,它會先后搜索ELF文件中DT_RPATH段、環境變量LD_LIBRARY_PATH、/etc/ld.so.cache文件列表、/lib/,/usr/lib目錄,找到鏈接庫文件后將其加載到內存;

    在程序執行時需要能夠找到鏈接庫文件:

    1) 將庫文件安裝到/lib或/usr/lib目錄下;

    2) 如果庫文件安裝在其他目錄,需要將路徑添加到/etc/ld.so.cache文件中,添加步驟如下:

    a) 編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑;

    b) 運行ldconfig,重建/etc/ld.so.cache文件;

    4. 總結

    在網上看到有的文章中把程序和庫文件的靜態和動態鏈接方式,比作書本和筆記的關聯方式;

    把書本上的內容比作程序,把參考書或者黑板上的筆記比作是要鏈接的目標;

    靜態鏈接,就像是把筆記抄寫到書本上,或者抄寫到活頁上,粘貼到書本上,將筆記和書本合為一個整體;這樣即使忘了帶參考書,或者黑板上的筆記被擦掉,都不會影響,因為筆記和書本已經融合了;

    優點是,效率更高了,看書方便多了;缺點是書本越來越厚;

    動態鏈接,就像是在書本中標記筆記的位置注釋,如:該部分參考什么什么書,第幾頁等信息,把筆記和書本分離稱互相獨立的個體,將筆記單獨整理稱庫文件;在閱讀到注釋的地方,需要翻看筆記時才按照注釋索引,查找筆記中對應的內容;動態鏈接的方式,需要書本和筆記同時在手,才能正常閱讀;

    優點是,不影響書本的空間;缺點是,查找筆記的效率比較低;

    參考資料

    《程序員的自我修養----鏈接、裝載與庫》

    靜態鏈接與動態鏈接的區別和使用

    深入淺出靜態鏈接和動態鏈接

    回到目錄

    總結

    以上是生活随笔為你收集整理的静态库调用_静态链接和动态链接对比简析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。