一. 什么是庫
庫是一個二進制文件,包含的代碼可被程序調(diào)用。例如標準C庫、數(shù)學庫、線程庫等等。庫有源碼,可下載后編譯,也可以直接安裝二進制包。 庫是事先編譯好的,可以復用的代碼,在OS上運行的程序基本上都要使用庫。使用庫可以提高開發(fā)效率。Windows和Linux下庫文件的格式不兼容。Linux下包含靜態(tài)庫和共享庫。
二. 靜態(tài)庫
靜態(tài)庫有如下特點
編譯(鏈接)時把靜態(tài)庫中相關代碼復制到可執(zhí)行文件中
程序中包含代碼,運行時不再需要靜態(tài)庫
程序運行時無需加載庫,運行速度更快
占用更多磁盤和空間
靜態(tài)庫升級后,程序需要重新編譯鏈接
靜態(tài)庫的創(chuàng)建與鏈接參考如下步驟: 第一步:確定庫中函數(shù)的功能、接口
第二步:編寫庫源碼
/****hello.c****/ #include#include"hello.h" voidhello(void){ printf("helloAndyxi "); }
/****hello.h****/ #ifndef_HELLO_H_ #define_HELLO_H_ voidhello(void); #endif
第三步:編譯生成目標文件
linux@linux:~/andy/lib$ls hello.chello.h linux@linux:~/andy/lib$gcc-chello.c-Wall linux@linux:~/andy/lib$ls hello.chello.hhello.o
第四步:創(chuàng)建靜態(tài)庫
linux@linux:~/andy/lib$ls hello.chello.hhello.o linux@linux:~/andy/lib$arcrslibhello.ahello.o//使用arcrs命令創(chuàng)建靜態(tài)庫 linux@linux:~/andy/lib$ls hello.chello.hhello.olibhello.a //注意libhello.a是庫文件名,hello是庫名 linux@linux:~/andy/lib$nmlibhello.a //使用nm命令可查看庫中符號信息 hello.o: 00000000Thello Uputs
第五步:編寫應用程序
/****test.c****/ #include#include"hello.h" intmain(intargc,constchar*argv[]){ hello(); return0; }
第六步:編譯應用程序并鏈接靜態(tài)庫
linux@linux:~/andy/lib$ls hello.chello.hhello.olibhello.atest.c linux@linux:~/andy/lib$gcc-otesttest.c-L.-l hello //使用-L.-l+庫名鏈接靜態(tài)庫 linux@linux:~/andy/lib$ls hello.chello.hhello.olibhello.atesttest.c linux@linux:~/andy/lib$./test helloAndyxi
由于使用的是靜態(tài)庫,編譯后相關代碼已經(jīng)復制到可執(zhí)行文件中。刪除靜態(tài)庫,不影響程序執(zhí)行
linux@linux:~/andy/lib$ls hello.chello.hhello.olibhello.atesttest.c linux@linux:~/andy/lib$rmlibhello.a linux@linux:~/andy/lib$ls hello.chello.hhello.otesttest.c linux@linux:~/andy/lib$./test helloAndyxi
三. 共享庫
共享庫有如下特點:
編譯(鏈接)時僅記錄用到哪個共享庫中的哪個符號,不復制共享庫中相關代碼
程序不包含庫中代碼,尺寸小
多個程序可共享一個庫
程序運行時需要加載庫
庫升級方便,無需重新編譯程序
使用更加廣泛
共享庫的創(chuàng)建與鏈接參考如下步驟: 第一步:確定庫中函數(shù)的功能、接口
第二步:編寫庫源碼
/****hello.c****/ #includevoidhello(void){ printf("helloworld "); return; }
/****bye.c****/ #includevoidbye(void){ printf("bye! "); return; }
/****共享庫頭文件common.h****/ #ifndef__COMMON_H__ #define__COMMON_H__ voidhello(void); voidbye(void); #endif
第三步:編譯生成目標文件
linux@linux:~/andy/lib/share$ls bye.ccommon.hhello.c linux@linux:~/andy/lib/share$gcc-c-fPIC*.c-Wall linux@linux:~/andy/lib/share$ls bye.cbye.ocommon.hhello.chello.o
fPIC選項:告訴編譯器生成位置無關代碼
位置無關代碼:生成的".o文件"文件中的代碼可以被加載到任意的地址執(zhí)行。編譯時用到了相對尋址而不是絕對尋址
第四步:創(chuàng)建共享庫common
linux@linux:~/andy/lib/share$gcc-shared-olibcommon.so.1hello.obye.o linux@linux:~/andy/lib/share$ls bye.cbye.ocommon.hhello.chello.olibcommon.so.1
shared選項:告訴編譯器生成一個共享庫
生成的共享庫的文件名叫"libcommon.so.1",其中".so"表示這是一個共享庫,".1"表示這個庫的版本是1
符號鏈接文件命名規(guī)則:lib<庫名>.so
第五步:編寫應用程序
/****test.c****/ #include#include"common.h" intmain(intargc,constchar*argv[]){ hello(); bye(); return0; }
第六步:編譯應用程序并鏈接共享庫
#****為共享庫文件創(chuàng)建鏈接文件****# linux@linux:~/andy/lib/share$ls bye.cbye.ocommon.hhello.chello.olibcommon.so.1test.c linux@linux:~/andy/lib/share$ln-slibcommon.so.1libcommon.so //ln-s創(chuàng)建符號鏈接 linux@linux:~/andy/lib/share$ls bye.cbye.ocommon.hhello.chello.olibcommon.solibcommon.so.1test.c
#****編譯應用程序并鏈接共享庫****# linux@linux:~/andy/lib/share$gcc-otesttest.c-L.-lcommon linux@linux-:~/andy/lib/share$ls bye.cbye.ocommon.hhello.chello.olibcommon.solibcommon.so.1testtest.c
gcc -o test test.c -L. -lcommon:可見此處共享庫和靜態(tài)庫用法相同;GCC在鏈接時首先找共享庫,如果共享庫不存在,則鏈接靜態(tài)庫,如果靜態(tài)庫也找不到,則報錯
加"-static"選項后,編譯器會直接去找靜態(tài)庫
共享庫的加載:如果完成上述步驟后就執(zhí)行程序,會報如下錯誤
linux@linux:~/andy/lib/share$./test ./test:errorwhileloadingsharedlibraries:libcommon.so:cannotopensharedobjectfile:Nosuchfileordirectory
出錯原因:因為程序鏈接的是共享庫,并沒有復制共享庫中的代碼,程序在執(zhí)行時會去加載用到的共享庫,加載時會去缺省路徑(比如"/lib","/usr/lib")下尋找共享庫,但是我們創(chuàng)建的庫在當前目錄下,并不在系統(tǒng)庫的搜索路徑里,所以在執(zhí)行時找不到共享庫,因此報錯
創(chuàng)建好共享庫后還需要添加共享庫加載路徑
第七步:加載共享庫并執(zhí)行程序
linux@linux:~/andy/lib/share$exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:. linux@linux:~/andy/lib/share$./test helloworld bye!
export 用于將原來的環(huán)境變量導出
":"前面的"$LD_LIBRARY_PATH"是引用原先的值;":"后面的"."是追加了當前目錄;還可追加其余共享庫的路徑,要用":"隔開
此方法是臨時的,只對當前終端有效。當重新打開一個終端再執(zhí)行改程序時又會報錯
為了讓系統(tǒng)能找到要加載的共享庫,通常由三種方法:
把庫拷貝到/usr/lib和/lib目錄下
在LD_LIBRARY_PATH環(huán)境變量中添加庫所在路徑
添加/etc/ld.so.conf.d/*.conf文件,執(zhí)行 ldconfig刷新
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11225瀏覽量
208914 -
函數(shù)
+關注
關注
3文章
4304瀏覽量
62427 -
靜態(tài)庫
+關注
關注
0文章
21瀏覽量
7422 -
編譯
+關注
關注
0文章
653瀏覽量
32806 -
共享庫
+關注
關注
0文章
4瀏覽量
5612
原文標題:Linux 中的靜態(tài)庫和共享庫
文章出處:【微信號:嵌入式攻城獅,微信公眾號:嵌入式攻城獅】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論