linux 动态库建立,浅析linux下静态库和动态库的建立和使用
在粵嵌學(xué)了很多知識,我們把常用的公用函數(shù)放在一起做成一個(gè)函數(shù)庫,可以供其他程序共同使用,函數(shù)庫本質(zhì)上說,是一個(gè)可執(zhí)行代碼的二進(jìn)制形式,可被操作系統(tǒng)載入內(nèi)存執(zhí)行。linux下的庫分為兩種:靜態(tài)庫,后綴名為
.a和動(dòng)態(tài)庫后綴名為.so(共享庫);
兩者的區(qū)別是:
靜態(tài)庫和動(dòng)態(tài)庫被載入應(yīng)用程序的時(shí)刻不同,調(diào)用靜態(tài)庫函數(shù)的應(yīng)用程序在編譯時(shí),會(huì)把靜態(tài)庫的代碼鏈接到目標(biāo)代碼中(也就是應(yīng)用程序的代碼中),因此程序所占內(nèi)存比較大,以后運(yùn)行此目標(biāo)程序時(shí)不再需要靜態(tài)庫;而動(dòng)態(tài)庫在程序編譯時(shí)不會(huì)鏈接到目標(biāo)代碼中,動(dòng)態(tài)庫只有在程序執(zhí)行時(shí),才被載入內(nèi)存,因此目標(biāo)程序所占空間小(如下圖),但是目標(biāo)程序每次運(yùn)行還要依賴這個(gè)動(dòng)態(tài)庫,所以如果這個(gè)動(dòng)態(tài)庫不存在了,則程序無法運(yùn)行。
那么,linux下是如何使用和創(chuàng)建自己的函數(shù)庫呢?我們以一個(gè)sin.c函數(shù)計(jì)算為例:
#include
int main(void)
{
float value;
value = sin ( 3.14 / 2 );
printf("%f\n",value);
}
我們編譯這個(gè)函數(shù):
gcc -o sin sin.c
出現(xiàn)以下錯(cuò)誤信息:
sin.c: In function 'main':
sin.c:5: warning: incompatible implicit declaration of built-in
function 'sin'
/tmp/cciDlilg.o(.text+0x2c): In function `main':
sin.c: undefined reference to `sin'
collect2: ld returned 1 exit status
‘undefined reference to sin’,說的是沒有 sin 的相關(guān)定義參考值!這是因?yàn)?C 語言里面的 sin
函示是寫在 libm.so
這個(gè)函式庫中,而我們并沒有在原始碼里面加入相關(guān)的說明,所以當(dāng)然就需要在編譯與連結(jié)的時(shí)候?qū)⑦@個(gè)函式庫給他連結(jié)進(jìn)執(zhí)行檔里面,所以可以這樣做:
gcc -o sin sin.c -L/usr/lib -lm
"-L"是指定libm.so庫所在的路徑(linux函數(shù)庫在/uer/lib中),-l是指定庫函數(shù)的名字,
“m ” :則是 libm.so 這個(gè)函式庫,其中, lib 與副檔名(.a 或 .so)不需要寫。
太棒了!終于編譯成功了。現(xiàn)在看看如何建立自己的庫!所有庫的都是由.o文件生成的,我們再看一個(gè)簡單的例子,先寫出以下三個(gè)程序:程序hello.c:
#include
void hello(const char *name)
{
printf("hello:%s!\n",name);
}
程序hello.h:
#ifdef HELLO_H
#define HELLO_H
void hello(const char *name)
#endif
程序main.c:
#include
int main()
{
hello("you are a good boy!");
return 0;
}
hello.c是我們要做的函數(shù)庫的源文件,里面包含庫函數(shù)hello();?hello.h是該庫函數(shù)的頭文件,main.c為測試這個(gè)函數(shù)庫的程序;?如果我們這樣編譯main.c程序,?gcc -o main
main.c?會(huì)出現(xiàn)以下錯(cuò)誤:?main.c:1:18:
error: hello.h: 沒有那個(gè)文件或目錄提示找不到頭文件,因?yàn)閔ello.h是我們自己寫的頭文件,標(biāo)準(zhǔn)c函數(shù)庫里面沒有這個(gè)頭文件,我們在編譯時(shí)加一個(gè)參數(shù)-I.,指明hello.h在當(dāng)前目錄路徑下(如果你放在其他路徑下,就改為:-I/頭文件路徑名):
gcc -o?main main.c -I.
不要開心太早,這時(shí)還會(huì)有錯(cuò)誤:
/tmp/ccr2NRXk.o: In function `main':
main.c:(.text+0x11): undefined reference to `hello'
collect2: ld returned 1 exit status
這個(gè)錯(cuò)誤是不是跟上面編譯sin函數(shù)時(shí)出現(xiàn)的“sin.c:
undefined reference to `sin”是不是很像,沒錯(cuò),找不到庫函數(shù)hello;因?yàn)槿笔〉?uer/lib里面沒有這個(gè)庫函數(shù),這時(shí)候我們就要自己做一個(gè)函數(shù)庫!先做一個(gè)靜態(tài)庫:1:將hello.c編譯成hello.o文件,無論靜態(tài)庫還是動(dòng)態(tài)庫都由.o文件生成:
gcc -c hello.c
2:由.o文件來創(chuàng)建靜態(tài)庫:靜態(tài)庫文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫名,擴(kuò)展名為.a。例如:我們將創(chuàng)建的靜態(tài)庫名為myhello,則靜態(tài)庫文件名就是libmyhello.a。在創(chuàng)建和使用靜態(tài)庫時(shí),需要注意這點(diǎn)。創(chuàng)建靜態(tài)庫用ar命令。
ar crv libmyhello.a
hello.o這是如果你看到libmyhello.a文件,說明你的靜態(tài)庫已經(jīng)創(chuàng)建成功了!現(xiàn)在我們看看如何使用這個(gè)靜態(tài)庫:在程序main.c中,我們包含了靜態(tài)庫的頭文件hello.h,然后在主程序main中直接調(diào)用公用函數(shù)hello。下面先生成目標(biāo)程序hello,然后運(yùn)行hello程序看看結(jié)果如何。
gcc -o main?main.c -L. -lmyhello
./main
hello:you are a good boy!
運(yùn)行成功,由于靜態(tài)庫是在編譯的鏈接到目標(biāo)程序中的,編譯成功后就不依賴靜態(tài)庫,此時(shí)你可以刪除靜態(tài)庫libmyhello.a,在運(yùn)行以下程序驗(yàn)證上面的說法!我們再來看看如何創(chuàng)建一個(gè)動(dòng)態(tài)庫:
1:動(dòng)態(tài)庫的命名個(gè)靜態(tài)庫一樣,也是在動(dòng)態(tài)庫名增加前綴lib,但其文件擴(kuò)展名為
.so。我們用gcc創(chuàng)建一個(gè)動(dòng)態(tài)庫名為myhello的文件:
gcc -shared -fPCI -o libmyhello.so hello.o
2:現(xiàn)在使用剛創(chuàng)建成功的libmyhello.so:在程序中使用動(dòng)態(tài)庫和使用靜態(tài)庫完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明動(dòng)態(tài)庫名進(jìn)行編譯。我們先運(yùn)行g(shù)cc命令生成目標(biāo)文件,再運(yùn)行它看看結(jié)果。
gcc -o main main.c -L. -lmyhello
./main
./main: error while loading shared libraries: libmyhello.so:
cannot open shared object file: No such file or directory
錯(cuò)
誤提示找不到動(dòng)態(tài)庫文件libmyhello.so。程序在運(yùn)行時(shí),會(huì)在/usr/lib和/lib等目錄中查找需要的動(dòng)態(tài)庫文件。若找到,則載入動(dòng)態(tài)
庫,否則將提示類似上述錯(cuò)誤而終止程序運(yùn)行。我們將文件libmyhello.so復(fù)制到目錄/usr/lib中,再試試。
# mv libmyhello.so /usr/lib
# ./main
Hello:you are a good boy!
成功。這也進(jìn)一步說明了動(dòng)態(tài)庫在程序運(yùn)行時(shí)是需要的。
一般情況下,我們?yōu)榱吮3?usr/liub庫的原始性,我們不把自己創(chuàng)建的動(dòng)態(tài)庫放在目錄/usr/lib中,而是在其他路徑下自己建立一個(gè)目錄,然后把我們自己的函數(shù)庫集中放在里面,這是編譯時(shí)就要修改環(huán)境變量LD_LIBRARY_PATH,指向自己創(chuàng)建的函數(shù)庫的路徑,在linux下可以用export命令來設(shè)置和查看這個(gè)環(huán)境變量;
另外:當(dāng)靜態(tài)庫和動(dòng)態(tài)庫同名時(shí),gcc將優(yōu)先使用動(dòng)態(tài)庫,可以自己驗(yàn)證以下!
總結(jié)
以上是生活随笔為你收集整理的linux 动态库建立,浅析linux下静态库和动态库的建立和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vxworks gcc linux,针对
- 下一篇: linux kill pid文件,从一次