知識不等於技術,這句話真的是越工作的時間長越深有體會,學習到的知識只有不斷的實踐,才成真正在自已的心里扎下根,成為自身的一部分,所以無論如何,我希望我的博客可以一直寫下去,慢慢的沉淀,終會有回報,無聊的時候想想,的確,寫代碼也是一種自娛自樂!
前幾天在做項目時出了一個問題,大體就是:makefile里在編譯可執行文件testappd的時候在有用-l去引用一個libtest.so,能編譯通過,但是在加載運行的時候系統提示找不到這個lib而導致進程啟動失敗。后來知道在產品版本編譯打包的時候這個lib並未被打包進去,這個問題后來解決了。但是出於好奇,我想搞清楚動態庫和靜態庫的概念,以及之前做過另一個項目時以dlopen方式去引用動態庫和makefile 去引用動態庫這幾種方式的不同。查找了網上的一些資料,看明白了,還需手動驗證一下才放心。
首先說說靜態鏈接庫,說實話,有時候真心感覺計算機這些相關的各種高大上的詞匯都是紙老虎,看上去高深的不行,其實當你捅開那層紙,就那么回事兒。
所謂靜態鏈接庫,說白了就是在你把寫好的代碼編譯的時候,就把你引用的庫一起給編進去了,從此后你編出來的執行程序跟外面都不再有任何關系,即使這個庫更新了,你也搭不上邊兒,其次,如果系統中許多類似的程序都需要用到這個庫,那么各自在編譯的時候都需要把這個庫給編進去,浪費存儲空間(加載到內存里應該也是浪費內存空間的)。linux系統中靜態庫的名字一般叫
xxx.a, 所以如果你看到一個以 .a結束的文件那么它多半就是一個靜態鏈接庫文件。
廢話少說,我們直接上干貨,看看靜態庫是如何被編譯出來以及如何被使用的
首先我們寫了一個sum.c,如下,很簡單,里面只有一個Sum函數,把兩個數相加的和返回
1 int Sum(int Number1, int Number2) 2 { 3 return Number1 + Number2; 4 }
當然還要寫一個聲明它的sum.h
int Sum(int Number1, int Number2);
最后來一個調用這個sum函數的主函數, 打印返回的結果
1 #include<stdio.h> 2 #include<sum.h> 3 4 void main() 5 { 6 int Num1 = 1; 7 int Num2 = 2; 8 int iRet = 0; 9 10 iRet = Sum(Num1, Num2); 11 printf("Num1 + Num2 = %d.", iRet); 12 return; 13 }
接下來我們編譯靜態庫,我的筆記本是mac os環境,打開終端后用vim寫代碼, gcc等相關工具直接就能用,版本沒注意,反正能用就行
1 192:zch kane$ ls 2 main.c sum.c sum.h 3 192:zch kane$ gcc -c sum.c 4 192:zch kane$ ls 5 main.c sum.c sum.h sum.o 6 192:zch kane$ 7 192:zch kane$ 8 192:zch kane$ ar cr libsum.a sum.o 9 192:zch kane$ ls 10 libsum.a main.c sum.c sum.h sum.o 11 192:zch kane$
如上,我們用ar這個工具來編譯靜態庫,cr標志告訴ar將object文件封裝
然后我們編譯主程序並運行:
192:zch kane$ gcc -o sumappd main.c -L . -lsum 192:zch kane$ ls libsum.a main.o sum.h sumappd main.c sum.c sum.o 192:zch kane$ ./sumappd Num1 + Num2 = 3
“-L .”指明了當前lib所在的路徑是在本目錄,-l表示鏈接libsum.a這個lib庫,很好理解。