編譯系統在編譯的過程中,將所有相關的目標模組打包成乙個單獨的檔案,稱為靜態庫(static library),它可以用做鏈結器的輸入。當鏈結器構造乙個輸出的可執行檔案時,它只拷貝靜態庫里被應用程式引用的目標模組。在unix系統中,靜態庫以一種稱為存檔(archive)的特殊檔案格式存放在磁碟中。存檔檔案是一組連線起來的可重定位目標檔案的集合,有乙個頭部用來描述每個成員目標檔案的大小和位置。存檔檔名由字尾
.a
標識。為了使我們對庫的討論更加形象具體,假設我們想在乙個叫做libvector.a
的靜態庫中提供如下的向量例程:
/* file name: addvec.c */
void addvec(int *x, int *y,
int *z, int n)
}
/* file name: multvec.c */
void multvec(int *x, int *y,
int *z, int n)
}
為了建立該庫,我們使用ar
工具:
unix> gcc -c addvec.c multvec.c
unix> ar rcs libvector.a addvec.o multvec.o
為了使用這個庫,我們可以編寫乙個應用(main.c
),它呼叫addvec
庫例程。(包含標頭檔案vector.h
定義了libvector.a
中例程的函式原型)。
/* file name: main.c */
#include
#include "vector.h"
int x[2] = ;
int y[2] = ;
int z[2];
int main()
/* file name: vector.h */
void addvec(int *x, int *y,
int *z, int n);
void multvec(int *x, int *y,
int *z, int n);
unix> gcc -o2
-c main.c
unix> gcc -static
-o p2 main.o ./libvector.a
下圖概括了鏈結器的行為。
靜態庫解決了許多關於如何讓大量相關函式對應用程式可用的問題。然而,靜態庫仍然有一些明顯的缺點。靜態庫和所有的軟體一樣,需要定期維護和更新。另乙個問題是幾乎每個c程式都使用標準i/o函式,如printf
和scanf
。在執行時,這些函式的**會被複製到每個執行程序的文字段中。在乙個執行50-100個程序的典型系統上,這將是對稀缺的儲存器系統資源的極大浪費。
共享庫(shared library)是致力於解決靜態庫缺陷的乙個現代創新產物。共享庫是乙個目標模組,在執行時,可以載入到任意的儲存器位址,並和乙個在儲存器中的程式鏈結起來。這個過程稱為動態鏈結(dynamic linking),是由乙個叫做動態鏈結器(dynamic linker)的程式來執行的。
共享庫也稱為共享目標(shared object),在unix系統中通常用.so
字尾來表示。微軟的作業系統大量地利用了共享庫,它們稱為dll(動態鏈結庫)。
共享庫是以兩種不同的方式來「共享」的。首先,在任何給定的檔案系統中,對於乙個庫只有乙個.so
檔案。所有引用該庫的可執行目標檔案共享這個.so
檔案中的**和資料,而不是像靜態庫的內容那樣被拷貝到引用它們的可執行的檔案中。其次,在儲存器中,乙個共享庫的.text
節的乙個副本可以被不同的正在執行的程序共享。
unix> gcc -shared -fpic -o libvector.so addvec.c multvec.c
unix> gcc -o p2 main.c ./libvector.so
鏈結過程如下圖:
靜態庫與動態庫
linux下靜態庫 a 的例子 mylib.h 位於include資料夾下 ifndef mylib h define mylib h int add int a,int b endif mylib.cpp 位於lib資料夾中 include mylib.h int add int a,int b ...
靜態庫與動態庫
庫本質上是一種可執行的二進位制 可以被作業系統載入 linux和windows的庫是不相容的 庫可以分為靜態塊和動態庫,二者的不同點在於 被載入的時刻不同。靜態庫 在程式編譯時會被連線到目標 中,程式執行時不再需要改靜態庫,體積較大,一般應用與移植過程中在宿主機上編譯的 靜態庫檔名的命名規範是以li...
靜態庫與動態庫
1.靜態庫 工程在呼叫靜態庫時,複製靜態庫,源 加長,不節省程式空間。字尾名.a 優點 程式設計後不需要再依賴庫 以空間換時間 建立靜態庫 gcc c 原始檔.c ar rcs rcu 靜態庫名 目標檔案1 目標檔案2 rc 靜態庫不存在,就建立該庫檔案 s 更新靜態庫 使用 gcc o file ...