今天由于要用到靜態鏈接庫,所以就學習了一下相關知識,總結如下:
靜態鏈接庫(一般命名為libxxx.a)就是很多.o文件的集合,在你的項目中如果有一個子模快,這個子模塊只是給總控模塊提供一個函數接口,那么你就可以考慮把這個子模快編譯成靜態鏈接庫libxxx.a,然后在總控模塊中編譯的時候,只需-L包含鏈接庫所在的目錄,再-lxxx引用鏈接庫就行.
當然,你也可以用動態鏈接庫,具體的動態鏈接庫創建和引用,做法和靜態鏈接庫大同小異,只是動態鏈接庫是在程序執行的時候是動態的添加到內存的,所以可以實現進程之間的資源共享.
另外動態鏈接庫可以做到所有的函數本著“有需求才調入”的原則,于是大大節省了系統資源:也就是說什么時候或者什么情況下,鏈接載入哪個動態鏈接庫函數,完全由程序員在程序代碼中控制。這樣,當你有一個相當大的工程,每次運行的時候,由于不同的操作需求,就只會有一小部分程序被載入內存。
具體給一個例子,先看一下工程的目錄結構:
$ ls -RF
.:
lib/ main.c Makefile
./lib:
Makefile.a Makefile.so string.h strlen.c strnlen.c
在工程主目錄下有main.c主控程序,Makefile文件和lib目錄
lib目錄下有string.h頭文件,strlen.c和strnlen.c,這三個文件里的函數就是我們想生成的庫函數
Makefile.a生成靜態鏈接庫的makefile文件
Makefile.so生成動態鏈接庫的makefile文件
好,讓我們看一看這些文件的具體內容:
頭文件string.h,聲明相關函數原形
$cat lib/string.h
int Strlen(char *pStr); int StrNlen(char *pStr, unsigned long ulMaxLen);
|
strlen.c:函數Strlen的實現,獲取給定字符串的長度
$cat lib/strlen.c
#include <stdio.h> #include <assert.h> int Strlen(char *pStr) { unsigned long ulLength; assert(NULL != pStr);
ulLength = 0; while(*pStr++) { ulLength++; } return ulLength; }
|
strnlen.c:函數StrNlen的實現,獲取給定字符串的長度,如果輸入字符串的長度大于指定的最大長度,則返回最大長度,否者返回字符串的實際長度
$cat lib/strnlen.c
#include<stdio.h> #include<assert.h> int StrNlen(char *pStr, unsigned long ulMaxLen) { unsigned long ulLength; assert(NULL != pStr); if(ulMaxLen <= 0) { printf("Wrong Max Length!\n"); return -1; } ulLength = 0; while(*pStr++ && ulLength < ulMaxLen) { ulLength++; } return ulLength; }
|
這三個文件是在lib/目錄下.
Makefile.a:生成靜態鏈接庫的makefile文件
$ cat lib/Makefile.a
libstr.a: strlen.o strnlen.o $(AR) r $@ $^ $(RM) $^
.PHONY : clean clean : rm -f libstr.a
|
Makefile.so:生成動態鏈接庫的makefile文件
$ cat Makefile.so
libstr.so: strlen.o strnlen.o gcc -fpic -shared -o $@ $^ $(RM) $^
.PHONY : clean clean : rm -f libstr.so
|
-fpic 使輸出的對象模塊是按照可重定位地址方式生成的
-shared指定把對應的源文件生成對應的動態鏈接庫文件libstr.so文件
main.c:總控程序
#include <stdio.h> #include "./lib/string.h" //靜態庫對應函數的頭文件
int main(int argc, char* argv[]) { char str[] = {"hello world"}; unsigned long ulLength = 0;
printf("The string is : %s\n", str); ulLength = Strlen(str); printf("The string length is : %d(use Strlen)\n", ulLength); ulLength = StrNlen(str, 10); printf("The string length is : %d(use StrNlen)\n", ulLength);
return 0; }
|
總控Makefile
$ cat Makefile
CC = gcc CFLAGS = -Wall -g LIBPATH = -L./lib LIB = -lstr main: main.o ( cd ./lib && make -f makefile.a ) || ( exit 1 ) # ( cd ./lib && make -f makefile.a && make -f makefile.so ) || ( exit 1 ) ${CC} ${CFLAGS} -o $@ main.o ${LIBPATH} ${LIB} .PHONY:clean clean: -rm -f main *.o ( cd ./lib && make -f makefile.a clean && make -f makefile.so clean ) || ( exit 1 )
|
動態鏈接庫和靜態鏈接庫使用時唯一的區別是需要加入動態庫的路徑:
在程序運行期間,也需要告訴系統去哪里找你的動態鏈接庫文件.在UNIX下是通過定義名為LD_LIBRARY_PATH 的環境變量來實現的.
只需將動態鏈接庫的目錄path賦值給此變量即可。為了讓執行程序順利找到動態庫,有三種方法:
1)把庫拷貝到/usr/lib和/lib目錄下.
2)在LD_LIBRARY_PATH環境變量中加上庫所在路徑.例如動態庫libstr.so在/home/xulei/test/lib目錄下,以bash為例,使用命令:
$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xulei/test/lib
在環境變量LD_LIBRARY_PATH后添加/home/xulei/test/lib
3) 修改/etc/ld.so.conf文件,把庫所在的路徑加到文件末尾
然后sudo ldconfig
這樣,加入的目錄下的所有庫文件都可見.
reference:
linux靜態鏈接庫與動態鏈接庫http://blog.chinaunix.net/u2/76292/showart_1274181.html
Linux靜態/動態鏈接庫的創建和使用http://dev.csdn.net/article/84/84562.shtm
from:
http://blog.chinaunix.net/u2/86590/showart.php?id=2138220
posted on 2010-04-25 11:52
chatler 閱讀(706)
評論(0) 編輯 收藏 引用 所屬分類:
Linux_Coding