靜態(tài)庫(kù)
- 靜態(tài)庫(kù)實(shí)際就是一些目標(biāo)文件(一般以.o結(jié)尾)的集合,靜態(tài)庫(kù)一般以.a結(jié)尾,只用于生成可執(zhí)行文件階段。
- 在鏈接步驟中匣屡,鏈接器將從庫(kù)文件取得所需代碼,復(fù)制到生成的可執(zhí)行文件中拇涤。這種庫(kù)稱為靜態(tài)庫(kù)捣作。其特點(diǎn)是可執(zhí)行文件中包含了庫(kù)代碼的一份完整拷貝,在編譯過(guò)程中被載入程序中鹅士。缺點(diǎn)就是多次使用就會(huì)有多份冗余拷貝券躁,并且對(duì)程序的更新和發(fā)布會(huì)帶來(lái)麻煩,如果靜態(tài)庫(kù)有更新掉盅,那么所有使用它的程序都需要重新編譯也拜、發(fā)布。
如何生成靜態(tài)庫(kù)趾痘?
# 1. 生成目標(biāo)文件
gcc -c test.c -o test.o
# 2. 使用ar命令將test.o打包成libtest.a靜態(tài)庫(kù)
# 選項(xiàng) r 更新或增加新文件到靜態(tài)庫(kù)
# 選項(xiàng) c 不管是否存在都創(chuàng)建庫(kù)
# 選項(xiàng) s 創(chuàng)建文檔索引(創(chuàng)建較大的庫(kù)可縮短編譯時(shí)間)
ar rcs libtest.a test.o
# 使用ar t libtest.a 查看靜態(tài)庫(kù)內(nèi)容
動(dòng)態(tài)庫(kù)
- 動(dòng)態(tài)庫(kù)在鏈接階段沒(méi)有被復(fù)制到程序中慢哈,而是在程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)加載到內(nèi)存中供程序調(diào)用。
- 系統(tǒng)只需載入一次動(dòng)態(tài)庫(kù)扼脐,不同的程序可以得到內(nèi)存中相同的動(dòng)態(tài)庫(kù)副本岸军,節(jié)省內(nèi)存開(kāi)銷。
如何生成動(dòng)態(tài)庫(kù)瓦侮?
# 1. 生成目標(biāo)文件
gcc -c test.c -o test.o
# 2. 使用 -fPIC(Position-Independent Code創(chuàng)建于地址無(wú)關(guān)的代碼) 和 -shared生成動(dòng)態(tài)庫(kù)
gcc -shared -fPIC -o libtest.so test.o
實(shí)戰(zhàn)
- 編寫工具代碼tool.c 查找數(shù)組中最大值艰赞,并在main.c中進(jìn)行調(diào)用
//tool.h
int find_max(int arr[], int n);
//tool.c
#include "tool.h"
int find_max(int arr[], int n){
int max = arr[0];
int i;
for(i = 0; i < n; i++){
if(arr[i] > max){
max = arr[i];
}
}
return max;
}
//main.c
#include <stdio.h>
#include "tool.h"
int main(){
int arr[] = {1, 3, 4, 8, 2};
int max = find_max(arr, 5);
printf("max = %d\n", max);
return 0;
}
- 將tool.c編譯成靜態(tài)庫(kù)
- 編譯可執(zhí)行文件并鏈接靜態(tài)庫(kù)
# -l 指定要鏈接的庫(kù)
# -L 按照指定庫(kù)尋找路徑("." 代表當(dāng)前目錄)
gcc -o main main.c -L -ltool
我們可以通過(guò) ls -lh 查看生成產(chǎn)物的大小,libtool.a只有918bytes而生成的main.exe卻有156kb這么大,這是為什么呢肚吏?
我們可以通過(guò) ldd main 查看可執(zhí)行文件依賴了哪些庫(kù)方妖。原來(lái)我們還依賴了這么多庫(kù)文件
我們?cè)谏梢淮蝿?dòng)態(tài)庫(kù)試一試
- 編譯動(dòng)態(tài)庫(kù)
gcc -shared -fPIC -o libtool.so tool.o
- 鏈接動(dòng)態(tài)庫(kù)(當(dāng)有同名靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)同時(shí)存在時(shí),gcc會(huì)優(yōu)先鏈接動(dòng)態(tài)庫(kù))
gcc -o main main.c -L. -ltool
- 執(zhí)行程序
? 如果我們直接執(zhí)行的話會(huì)報(bào) No such file or directory 找不到可執(zhí)行文件
? 我們可以為執(zhí)行程序設(shè)置環(huán)境變量 LD_LIBRARY_PATH=. ./main 設(shè)置除默認(rèn)路徑外查找共享庫(kù)路徑
靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)區(qū)別
載入時(shí)刻不同
- 靜態(tài)庫(kù)在程序編譯時(shí)會(huì)鏈接到目標(biāo)代碼中罚攀,程序運(yùn)行時(shí)不在需要靜態(tài)庫(kù)党觅,因此體積較大。而且每次編譯都需要載入靜態(tài)代碼斋泄,因此內(nèi)存開(kāi)銷大杯瞻。
- 動(dòng)態(tài)庫(kù)在程序編譯時(shí)不會(huì)被鏈接到目標(biāo)代碼中,而是在程序運(yùn)行時(shí)才被載入炫掐,程序運(yùn)行時(shí)需要?jiǎng)討B(tài)庫(kù)存在魁莉,因此體積較小。而且系統(tǒng)只需載入一次募胃,不同程序可以得到內(nèi)存中相同的動(dòng)態(tài)庫(kù)副本旗唁,因此內(nèi)存開(kāi)銷小。