Linux 中的應(yīng)用程序以以下兩種方式之一鏈接到外部函數(shù):要么在構(gòu)建時(shí)與靜態(tài)庫(kù)( lib*.a)靜態(tài)地鏈接,并且將庫(kù)代碼包含在該應(yīng)用程序的可執(zhí)行文件里;要么在運(yùn)行時(shí)與共享庫(kù)( lib*.so)動(dòng)態(tài)地鏈接。通過動(dòng)態(tài)鏈接裝入器,將動(dòng)態(tài)庫(kù)映射進(jìn)應(yīng)用程序的可執(zhí)行內(nèi)存中。在啟動(dòng)應(yīng)用程序之前,動(dòng)態(tài)鏈接裝入器將所需的共享目標(biāo)庫(kù)映射到應(yīng)用程序的內(nèi)存,或者使用系統(tǒng)共享的目標(biāo)并為應(yīng)用程序解析所需的外部引用。現(xiàn)在應(yīng)用程序就可以運(yùn)行了。
先介紹靜態(tài)庫(kù):
靜態(tài)函數(shù)庫(kù)實(shí)際上就是簡(jiǎn)單的一個(gè)普通的目標(biāo)文件的集合,一般來(lái)說習(xí)慣用“.a”作為文件的后綴。可以用ar這個(gè)程序來(lái)產(chǎn)生靜態(tài)函數(shù)庫(kù)文件。Ar 是archiver的縮寫。靜態(tài)函數(shù)庫(kù)現(xiàn)在已經(jīng)不在像以前用得那么多了,主要是共享函數(shù)庫(kù)與之相比較有很多的優(yōu)勢(shì)的原因。慢慢地,大家都喜歡使用共享函數(shù) 庫(kù)了。不過,在一些場(chǎng)所靜態(tài)函數(shù)庫(kù)仍然在使用,一來(lái)是保持一些與以前某些程序的兼容,二來(lái)它描述起來(lái)也比較簡(jiǎn)單。
靜態(tài)庫(kù)函數(shù)允許程序員把程序link起來(lái)而不用重新編譯代碼,節(jié)省了重新編譯代碼的時(shí)間。不過,在今天這么快速的計(jì)算機(jī)面前,一般的程序的重新 編譯也花費(fèi)不了多少時(shí)間,所以這個(gè)優(yōu)勢(shì)已經(jīng)不是像它以前那么明顯了。靜態(tài)函數(shù)庫(kù)對(duì)開發(fā)者來(lái)說還是很有用的,例如你想把自己提供的函數(shù)給別人使用,但是又想 對(duì)函數(shù)的源代碼進(jìn)行保密,你就可以給別人提供一個(gè)靜態(tài)函數(shù)庫(kù)文件。理論上說,使用ELF格式的靜態(tài)庫(kù)函數(shù)生成的代碼可以比使用共享函數(shù)庫(kù)(或者動(dòng)態(tài)函數(shù) 庫(kù))的程序運(yùn)行速度上快一些,大概1-5%。
假設(shè)有下面幾個(gè)文件:String.h,Strlen.c,Strlnen.c:
String.h,聲明相關(guān)函數(shù)原形;
/***********************************
Filename : String.h
Description :
Author : HCJ
Date : 2006-5-7
************************************/
int Strlen(char *pStr);
int StrNlen(char *pStr, unsigned long ulMaxLen);
Strlen.c:函數(shù)Strlen的實(shí)現(xiàn),獲取給定字符串的長(zhǎng)度;
/**************************************
Filename : get string length
Description :
Author : HCJ
Date : 2006/5/7
**************************************/
#include<stdio.h>
#include<assert.h>
int Strlen(char *pStr)
{
unsigned long ulLength;
assert(NULL != pStr);
ulLength = 0;
while(*pStr++)
{
ulLength++;
}
return ulLength;
}
Strlnen.c:函數(shù)StrNlen的實(shí)現(xiàn),獲取給定字符串的長(zhǎng)度,如果輸入字符串的長(zhǎng)度大于指定的最大長(zhǎng)度,則返回最大長(zhǎng)度,否者返回字符串的實(shí)際長(zhǎng)度;
/**********************************************
Fileneme: mystrnlen.c
Description: get input string length,if string large
max length input return max length,
else real length
Author: HCJ
Date : 2006-5-7
**********************************************/
#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;
}
生成靜態(tài)鏈接庫(kù):
利用GCC生成對(duì)應(yīng)目標(biāo)文件:
#>gcc –c Strlen.c Strnlen.c
如果對(duì)應(yīng)的文件沒有錯(cuò)誤,gcc會(huì)對(duì)文件進(jìn)行編譯生成Strlen.o和Strnlen.o兩個(gè)目標(biāo)文件(相當(dāng)于windows下的obj文件)。然后用ar創(chuàng)建一個(gè)名字為libstr.a的庫(kù)文件,并把Strlen.o 和Strnlen.o的內(nèi)容插入到對(duì)應(yīng)的庫(kù)文件中。,相關(guān)命令如下:
#>ar –rc libstr.a Strlen.o Strnlen.o
命令執(zhí)行成功以后,對(duì)應(yīng)的靜態(tài)庫(kù)libstr.a已經(jīng)成功生成。
靜態(tài)庫(kù)的使用:
假設(shè)有下面的文件要使用對(duì)應(yīng)的的靜態(tài)庫(kù):
編譯生成對(duì)應(yīng)的目標(biāo)文件:
#>gcc -c -I/home/hcj/xxxxxxxx main.c
生成可執(zhí)行文件:
#>gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.a
其中-I/home/hcj/xxxxxxxx和-L/home/hcj/xxxxxxxx是通過-I和-L指定對(duì)應(yīng)的頭文件和庫(kù)文件的路徑。libstr.a是對(duì)應(yīng)的靜態(tài)庫(kù)的名稱。這樣對(duì)應(yīng)的靜態(tài)庫(kù)已經(jīng)編譯到對(duì)應(yīng)的可執(zhí)行程序中。執(zhí)行對(duì)應(yīng)的可執(zhí)行文件便可以對(duì)應(yīng)得函數(shù)調(diào)用的結(jié)果。
/*****************************************
FileName: main.c
Description: test static/dynamic library
Author: HCJ
Date : 2005-5-7
******************************************/
#include<stdio.h>
#include “String.h” //靜態(tài)庫(kù)對(duì)應(yīng)函數(shù)的頭文件
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;
}
這篇文章也不錯(cuò),就是不太整潔: