1. 程式人生 > >linux 靜態鏈接和動態鏈接

linux 靜態鏈接和動態鏈接

g++ -o 允許 合並 動態 打包成 font 符號 初始

  • 鏈接

一個可執行目標文件的生成需要經過預編譯(g++ -E)、編譯(g++ -S)、匯編(g++ -c)、鏈接四個步驟。鏈接是將多個可重定位目標文件合並到一個目標文件的過程。鏈接由鏈接器完成,鏈接器重要完成兩個任務:

1、符號(符號表由匯編器構造)解析。也就是將符號引用和符號定義關聯起來。其中符號定義和符號引用可能不在同一個目標文件中。而且鏈接器對多重定義的全局符號的解析有一定的規則:不允許有多個同名強符號(函數和初始化了的全局變量)、如果有一個強符號和多個弱符號同名選擇強符號、如果有多個弱符號隨機選擇一個。

2、重定位。包括將不同可重定位目標文件的相應的節合並為一個節,以及重定位符號引用,使得對符號的引用都指向正確的運行時地址。

  • 靜態鏈接

1、生成靜態庫

# g++ -c a.cc b.cc

# g++ ar rcs libab.a a.o b.o

# g++ -static -o prog main.o ./libab.a

通過以上形式,可以將多個目標模塊打包成一個單獨的文件,稱為靜態庫。與靜態庫鏈接時,只復制被程序引用的目標模塊,但是有一點需要註意:在鏈接形成最終的可執行文件時,命令行中文件出現的順序必須正確。即符號定義必須出現在符號引用之後。所以庫一般放在命令行的最後。

靜態鏈接具有以下缺點:

多個進程引用相同的目標模塊,則在內存上會有多個副本,從而浪費內存

如果靜態庫有更新,則需要重新鏈接。

  • 動態鏈接

動態鏈接分為加載時鏈接和運行時鏈接。

加載時鏈接,在鏈接階段鏈接器會復制一些重定位和符號表信息,而在加載時重定位動態庫的文本和數據到一個內存段,有多個進程使用同一個動態庫時,將使用內存映射的方法共享代碼和數據,並且內存中只有一份副本。

運行時鏈接則是通過顯示調用系統函數的方式。

運行時鏈接

linux 靜態鏈接和動態鏈接