静态库和动态库详解(部分参考别人)
靜態(tài)庫和動態(tài)庫的區(qū)別
1.?靜態(tài)函數(shù)庫
????這類庫的名字一般是libxxx.a;利用靜態(tài)函數(shù)庫編譯成的文件比較大,因為整個?函數(shù)庫的所有數(shù)據(jù)都會被整合進目標代碼中,他的優(yōu)點就顯而易見了,即編譯后的執(zhí)行程序不需要外部的函數(shù)庫支持,因為所有使用的函數(shù)都已經(jīng)被編譯進去了。當然這也會成為他的缺點,因為如果靜態(tài)函數(shù)庫改變了,那么你的程序必須重新編譯。
2.?動態(tài)函數(shù)庫
????這類庫的名字一般是libxxx.so;相對于靜態(tài)函數(shù)庫,動態(tài)函數(shù)庫在編譯的時候?并沒有被編譯進目標代碼中,你的程序執(zhí)行到相關(guān)函數(shù)時才調(diào)用該函數(shù)庫里的相應(yīng)函數(shù),因此動態(tài)函數(shù)庫所產(chǎn)生的可執(zhí)行文件比較小。由于函數(shù)庫沒有被整合進你的程序,而是程序運行時動態(tài)的申請并調(diào)用,所以程序的運行環(huán)境中必須提供相應(yīng)的庫。動態(tài)函數(shù)庫的改變并不影響你的程序,所以動態(tài)函數(shù)庫的升級比較方便。
linux系統(tǒng)有幾個重要的目錄存放相應(yīng)的函數(shù)庫,如/lib?/usr/lib。
?
?
動態(tài)庫制作
實例說明:
假設(shè)當前目錄有一下文件:
/main.c//#include<math2.h>頭文件是我自己的
??1?#include<stdio.h>
??2?#include<math2.h>
??3?int?main(){
??4?????????int?i=11,j=22;
??5?????????printf("__%d__\n",myadd(i,j));
??6?????????return?0;
??7?}
?
math2.h///?????
??1?#ifndef?_MATH2_H_
??2?????????#define?_MATH2_H_
??3?????????int?myadd(int?,int?);
??4?#endif
?
/myadd.c//??????????????????????????????????????
??1?int?myadd(int?i,int?j){
??2?????????return?i+j;
??3?}
???
對于頭文件這里用兩種情況:
情況一:將其放到/usr/include/
情況二:在編譯時通過-I來指定需要用到的頭文件在那個目錄
?
動態(tài)庫制作使用:????????????????????????????
現(xiàn)在我要將myadd.c制作成動態(tài)庫,使得main.c能夠使用該動態(tài)庫
第一步:gcc?-c?myadd.c?-o?myadd.o?-fpic
//用到fpic參數(shù)的原因:myadd.o需要來制作庫文件,庫文件不同于一般
的二進制文件,他需要一些特殊的格式和特殊的信息,因此用-fpic來生成這些特
殊格式和信息
?
第二步:gcc?-shared?-WL,-soname,libmath.so.1?-o?libmath-1.0.0.so?
myadd.o
//-shared表示要生成動態(tài)庫;-wl,-sonname,libmyadd.so.1將會導(dǎo)致字
符串libmyadd.so.1作為文件名稱被記錄在最終生成的庫文件libmath-1.0.0.so中
。
?
ok至此生成了該動態(tài)庫,但是此時還不能使用,需要下面在做一些工作:
有兩種情況使用該動態(tài)庫:
?
情況一:將其放到系統(tǒng)庫中
第一步:cp?libmath-1.0.0.so?/lib/
注意此時用到的庫名是math;
?
第二步:但是此時通過gcc?main.c?-lmath還是不能編譯成功,這是因為,編譯器
到系統(tǒng)庫中找到庫,是找libmath.so,而不是直接找libmath-1.0.0.so,因而需要
在/lib/下建立libmath-1.0.0.so的軟連接:
ln?-s?/lib/libmath-1.0.0.so?libmath.so
?
第三步:在gcc編譯后的文件還是不能執(zhí)行,這是因為,我們在制作動態(tài)庫的時候
指定了鏈接的庫名是libmath.so.1(但是我們真正的庫是libmath-1.0.0.so),因
而我們還需要創(chuàng)建一個關(guān)于libmath-1.0.0.so的軟連接:
ln?-s?/lib/libmath-1.0.0.so?libmath.so.1
上面的工作做完之后就可以完全的將制作的動態(tài)庫使用在我們的應(yīng)用程序,即編
譯和運行都可以通過
?
情況二:可以將頭文件以及生成的庫,還有關(guān)于該庫的兩個軟連接放到當前(或
者你指定的目錄下);
第一步:將情況二說的文件生成并一一放到當前目錄下?
第二步:此時編譯需要用到:
gcc?main.c?-L.?-I.?
//對于-L是用于指定在編譯時需要用到庫搜索路徑?//對于-I是用于指定
在編譯時頭文件的存放目錄
第三步:在編譯成功后的文件還是不能直接運行,需要添加一個環(huán)境變量在指定
在鏈接庫時的搜索路勁(注意不能寫錯了變量名):
????export?LD_LIBRARY_PATH=/hyg/linux高級編程/文件IO/jingtai
?
完了之后在自己設(shè)定的目錄下就可以運行自己生成的動態(tài)庫文件。
?
?
靜態(tài)庫的制作:
情況一:放到系統(tǒng)庫中
?
第一步:?gcc?-c?myadd.c?-o?myadd.o
第二步:ar?rc?libmyadd.a?myadd.o
//第二步是制作靜態(tài)庫
第三步:cp?libmyadd.a?/lib/
第四步:gcc?mian.c?-lmyadd??-I.?-static
?
情況二:可以放到指定目錄,在編譯時需要指定路徑,方法同動態(tài)庫的情況二
?
此下面部分轉(zhuǎn)于:http://www.cnblogs.com/feisky/archive/2010/03/09/1681996.html
動態(tài)庫的顯式調(diào)用?
??顯式調(diào)用動態(tài)庫需要四個函數(shù)的支持,??函數(shù)?dlopen?打開動態(tài)庫,??函數(shù)?dlsym?獲取動態(tài)庫中對象基址,??函數(shù)?dlerror?獲取顯式動態(tài)庫操作中的錯誤信息,??函數(shù)?doclose?關(guān)閉動態(tài)庫.
[bill@billstone?make_lib]$?cat?main.c?
#include?<dlfcn.h>?
int?main()?
{?
????????????????void?*pHandle;?
????????????????void?(*pFunc)();????????????????????????????????????????????????????//??指向函數(shù)的指針?
????????????????int?*p;?
????????????????pHandle?=?dlopen("./d1.so",?RTLD_NOW);??????????????????//??打開動態(tài)庫?
????????????????if(!pHandle){?
????????????????????????????????printf("Can't?find?d1.so?\n");?
????????????????????????????????exit(1);?
????????????????}?
????????????????pFunc?=?(void?(*)())dlsym(pHandle,?"print");????????????????//??獲取庫函數(shù)?print?的地址?
????????????????if(pFunc)?
????????????????????????????????pFunc();?
????????????????else?
????????????????????????????????printf("Can't?find?function?print\n");?
????????????????p?=?(int?*)dlsym(pHandle,?"p");??????????????????????????????????????//??獲取庫變量?p?的地址?
????????????????if(p)?
????????????????????????????????printf("p?=?%d\n",?*p);?
????????????????else?
????????????????????????????????printf("Can't?find?int?p\n");?
????????????????dlclose(pHandle);????????????????????????????????????????????????????????????????//??關(guān)閉動態(tài)庫?
????????????????return?0;?
}?
[bill@billstone?make_lib]$?gcc?-o?tds?main.c?–ld1?–L.
此時還不能立即./tds,因為在動態(tài)函數(shù)庫使用時,會查找/usr/lib、/lib目錄下的動態(tài)函數(shù)庫,而此時我們生成的庫不在里邊。?這個時候有好幾種方法可以讓他成功運行:?最直接最簡單的方法就是把libstr_out.so拉到/usr/lib或/lib中去。?還有一種方法?export?LD_LIBRARY_PATH=$(pwd)?另外還可以在/etc/ld.so.conf文件里加入我們生成的庫的目錄,然后/sbin/ldconfig。?/etc/ld.so.conf是非常重要的一個目錄,里面存放的是鏈接器和加載器搜索共享庫時要檢查的目錄,默認是從/usr/lib?/lib中讀取的,所以想要順利運行,我們也可以把我們庫的目錄加入到這個文件中并執(zhí)行/sbin/ldconfig?。另外還有個文件需要了解/etc/ld.so.cache,里面保存了常用的動態(tài)函數(shù)庫,且會先把他們加載到內(nèi)存中,因為內(nèi)存的訪問速度遠遠大于硬盤的訪問速度,這樣可以提高軟件加載動態(tài)函數(shù)庫的速度了。
庫依賴的查看
使用ldd命令來查看執(zhí)行文件依賴于哪些庫。
該命令用于判斷某個可執(zhí)行的?binary?檔案含有什么動態(tài)函式庫。
[root@test?root]#?ldd?[-vdr]?[filename]
參數(shù)說明:
--version 打印ldd的版本號
-v?--verbose 打印所有信息,例如包括符號的版本信息
-d?--data-relocs 執(zhí)行符號重部署,并報告缺少的目標對象(只對ELF格式適用)
-r?--function-relocs 對目標對象和函數(shù)執(zhí)行重新部署,并報告缺少的目標對象和函數(shù)(只對ELF格式適用)
--help?用法信息。
如果命令行中給定的庫名字包含'/',這個程序的libc5版本將使用它作為庫名字;否則它將在標準位置搜索庫。運行一個當前目錄下的共享庫,加前綴"./"。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/jiangu66/p/3202848.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的静态库和动态库详解(部分参考别人)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Android Training视频系
- 下一篇: SPOJ-OPTM Optimal Ma