1. 程式人生 > 其它 >動態庫和靜態庫

動態庫和靜態庫

區別

假設庫的大小是500M
靜態庫的時候,是把庫都編譯程序序中,每一個程式就多一個500M,因為實在自己程式裡,所以呼叫的時候速度快
動態庫是所有程式共享這個一個庫,動態庫會先儲存在記憶體中,程式需要的時候會呼叫,比在自己的程式碼裡多了一個進入記憶體的操作,所以速度比靜態庫慢

  • 靜態庫適用於對空間需求低,速度需求高的場景,比如作業系統的啟動
  • 動態庫適用於對空間要求高,時間要求低的場景,比如資料庫

靜態庫的製作和使用

靜態庫製作程式碼

ar rcs libmylib.a file.o

前兩個命令是固定的,第二個c是不存在就建立的意思,第三個是製作的靜態庫的名字,第四個是輸出檔案
注意:靜態庫的名字必須以lib開頭,mylib為自己的名字,.a為字尾


例子:
首先建立一個add.c, sub.c, div1.c

輸出.o檔案記得加-c


再移動一下

再也一個測試檔案

注意:編譯時候的錯誤會出現行號,沒有出現行號是連結時候的錯誤


如下圖可知,編譯出來的檔案比較大

gcc的時候,注意.c檔案在前,靜態庫在後
注意上面有警告,隱式宣告,出現在編譯階段。當沒有函式定義或沒有函式宣告的情況下,編譯器會作隱式宣告。但是編譯器一般只會宣告 int 函式名(int, int )這種,出現void * 函式名的時候就不行了,容易出現錯誤
上述問題解決辦法就是在test.c中隱式宣告三個函式:
int add(int, int)
int sub(int, int)
int div1(int, int)
再但是:
上面操作是我自己做的靜態庫,在網上下的時候,並不知道函式名字
,所以一般靜態庫製作者會再製作一個頭檔案宣告這些函式,在使用的時候呼叫標頭檔案即可。

動態庫的製作和使用

第一步同靜態庫,也是將.c檔案生成.o檔案。(生成與位置無關的程式碼
注意:動態庫裡面的函式,只有當呼叫程式執行到動態庫的函式位置上時才會呼叫動態庫,即呼叫的動態庫的函式地址是動態在變的,因為動態庫在變
地址回填:

動態庫的函式在沒呼叫之前是沒有地址的,使用反彙編
objdump -dS test > out

由圖可知,是根軍@plt來繫結地址的。

  1. 所以生成動態庫的時候使用
gcc -c add.c -o add.o -fPIC

這樣生成的add裡面的函式都是plt地址的
2. 再使用

gcc -shared -o lib名字.so add.o sub.o div1.o

製作動態庫
3. 使用動態庫:編譯可執行檔案時要指定動態庫
-l, 用來指定庫名
-L, 用來指定庫路徑

gcc test.c -o test.out -l mylib -L ./lib

注意使用的時候要去掉lib和.so


如圖所示出錯了。
出錯原因:
連結器: 工作與連結階段,在a.out檔案執行前,工作的時候需要l和L
動態連結器: 工作在程式執行階段,需要提供程式動態連結庫所在位置,如果沒有提供,就會去LD_LIBRARY_PATH的環境變數找

但是環境變數是程序的概念,用export之後,開啟新的程序就沒了。永久生效~./bashrc,更改,然後source 它或者. 執行或者重啟,建議使用永久路徑
第三種方法,也可以直接複製到./lib下
ldd a.out: 檢視可執行檔案的動態庫路徑
第四種方法,vim /etc/ld.so.conf
加入動態庫路徑,再輸入 sudo ldconfig -v載入一下

資料段合併


連結的時候會合並程式碼段和制度資料段,合併的好處是為了節省空間, 通過MMU對映,4kb是一頁(磁碟是512k),這兩段比較小,用不了8k,所以合併。
。bss和.data也會合並

主要是給自己看的,所以肯定會出現很多錯誤哈哈哈哈哈