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