Linux 中的應用程式以以下兩種方式之一連結到外部函數:要麼在構建時與靜態庫( lib*.a)靜態地連結,並且將庫程式碼封裝含在該應用程式的可執行檔裡;要麼在運行時與共用庫( lib*.so)動態地連結。通過動態連結裝入器,將動態庫映射進應用程式的可執行記憶體中。在啟動應用程式之前,動態連結裝入器將所需的共用目標庫映射到應用程式的記憶體,或者使用系統共用的目標並為應用程式解析所需的外部參考。現在應用程式就可以運行了。
先介紹靜態庫:
靜態函數庫實際上就是簡單的一個普通的目標檔案的集合,一般來說習慣用“.a”作為檔案的尾碼。可以用ar這個程式來產生靜態函數庫檔案。Ar 是archiver的縮寫。靜態函數庫現在已經不在像以前用得那麼多了,主要是共用函數庫與之相比較有很多的優勢的原因。慢慢地,大家都喜歡使用共用函數 庫了。不過,在一些場所靜態函數庫仍然在使用,一來是保持一些與以前某些程式的相容,二來它描述起來也比較簡單。
靜態庫函數允許程式員把程式link起來而不用重新編譯代碼,節省了重新編譯代碼的時間。不過,在今天這麼快速的電腦面前,一般的程式的重新 編譯也花費不了多少時間,所以這個優勢已經不是像它以前那麼明顯了。靜態函數庫對開發人員來說還是很有用的,例如你想把自己提供的函數給別人使用,但是又想 對函數的原始碼進行保密,你就可以給別人提供一個靜態函數庫檔案。理論上說,使用ELF格式的靜態庫函數產生的程式碼可以比使用共用函數庫(或者動態函數 庫)的程式運行速度上快一些,大概1-5%。
假設有下面幾個檔案:String.h,Strlen.c,Strlnen.c:
String.h,聲明相關函數原形;
/***********************************
Filename : String.h
Description :
Author : HCJ
Date : 2006-5-7
************************************/
int Strlen(char *pStr);
int StrNlen(char *pStr, unsigned long ulMaxLen);
Strlen.c:函數Strlen的實現,擷取給定字串的長度;
/**************************************
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:函數StrNlen的實現,擷取給定字串的長度,如果輸入字串的長度大於指定的最大長度,則返回最大長度,否者返回字串的實際長度;
/**********************************************
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;
}
產生靜態連結庫:
利用GCC產生對應目標檔案:
#>gcc –c Strlen.c Strnlen.c
如果對應的檔案沒有錯誤,gcc會對檔案進行編譯產生Strlen.o和Strnlen.o兩個目標檔案(相當於windows下的obj檔案)。然後用ar建立一個名字為libstr.a的庫檔案,並把Strlen.o 和Strnlen.o的內容插入到對應的庫檔案中。,相關命令如下:
#>ar –rc libstr.a Strlen.o Strnlen.o
命令執行成功以後,對應的靜態庫libstr.a已經成功產生。
靜態庫的使用:
假設有下面的檔案要使用對應的的靜態庫:
編譯產生對應的目標檔案:
#>gcc -c -I/home/hcj/xxxxxxxx main.c
產生可執行檔:
#>gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.a
其中-I/home/hcj/xxxxxxxx和-L/home/hcj/xxxxxxxx是通過-I和-L指定對應的標頭檔和庫檔案的路徑。libstr.a是對應的靜態庫的名稱。這樣對應的靜態庫已經編譯到對應的可執行程式中。執行對應的可執行檔便可以對應得函數調用的結果。
/*****************************************
FileName: main.c
Description: test static/dynamic library
Author: HCJ
Date : 2005-5-7
******************************************/
#include<stdio.h>
#include “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;
}