Static libraries
把一堆object檔用ar(archiver)包裝集合起來,檔名以".a" 結尾。
優點
執行效能通常會比shared libraries與dynamically loaded快,
不易發生執行時找不到library或版本錯置而無法執行的問題。
缺點
檔案較大,維護度較低;例如library如果發現bug需要更新,那麼就必須重新連結執行檔。
範例
gcc -c hello.c world.c /* 編出hello.o 與world.o */
ar rcs libmylib.a hello.o world.o /* 包成limylib.a */
如果想要配合gcc 的"-l" 參數來連結,一定要以"lib" 開頭,中間是自定的library名稱,然後緊接著".a" 結尾。
gcc main.c libmylib.a
或
gcc main.c -L. -lmylib
參數"-L"用來指定要搜尋程式庫的目錄,`.’ 表示搜尋現在所在的目錄,通常預設會搜/usr/lib 或/lib 等目錄。
Shared library
shared library是在程式起始時就要被載入,而不是執行中用到才載入,而且在連結階段需要有該程式庫才能進行連結。
soname 用來表示一個特定library 的名稱,像是libmylib.so.1 。以"lib" 開頭,接著是該library 的名稱,然後是".so",接著是版號。
real name 是實際放有library程式的檔案名稱,後面會再加上minor 版號與release 版號,像是libmylib.so.1.0.0 。
linker name是用於連結時的名稱,是不含版號的soname ,如: libmylib.so。通常linker name與real name是用ln 指到對應的real name ,用來提供彈性與維護性。
範例
gcc -c -fPIC hello.c world.c
加上-fPIC 用來產生position-independent code
gcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.0 hello.o world.o
-shared 表示要編譯成shared library
-Wl 用於參遞參數給linker,因此-soname與libmylib.so.1會被傳給linker處理。
-soname用來指名soname 為limylib.so.1
library會被輸出成libmylib.so.1.0.0 (也就是real name)
可以用objdump 來看library 的soname。
objdump -p libmylib.so | grep SONAME
編譯後再用ln 來建立soname 與linker name 兩個檔案。
ln -s libmylib.so.1.0.0 libmylib.so
ln -s libmylib.so.1.0.0 libmylib.so.1
gcc main.c libmylib.so
或
gcc main.c -L. -lmylib //linker會搜尋libmylib.so 來進行連結。
如果目錄下同時有static與shared library的話,會以shared為主,使用-static 參數可以避免使用shared連結:
gcc main.c -static -L. -lmylib
可以用ldd 看編譯出的執行檔與shared程式庫的相依性
ldd a.out
若執行時找不到libmylib.so.1而無法執行程式,有幾個方式可以處理:
a. 把libmylib.so.1 安裝到系統的library目錄,如/usr/lib下。
b. 設定/etc/ld.so.conf ,加入一個新的library搜尋目錄,並執行ldconfig更新快取。
c. 設定LD_LIBRARY_PATH 環境變數來搜尋library,這個例子是加入目前的目錄來搜尋要載作的library。
$ LD_LIBRARY_PATH=. ./a.out
Dynamically loaded libraries
Dynamicaaly loaded libraries 才是像windows 所用的DLL ,在使用到時才載入,編譯連結時不需要相關的library。動態載入庫常被用於像plug-ins的應用。
動態載入是透過一套dl function來處理。
範例
#include <dlfcn.h>
void *dlopen(const char *filename, int flag); //開啟載入filename 指定的library。
void *dlsym(void *handle, const char *symbol); //取得symbol 指定的symbol name在library被載入的記憶體位址。
int dlclose(void *handle); //關閉dlopen開啟的handle。
char *dlerror(void); //傳回最近所發生的錯誤訊息。
編譯時要加上-ldl 參數來與dl library 連結
gcc dltest.c -ldl
____ dltest.c ____
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main()
{
void *handle;
void (*f)();
char *error;
/* 開啟之前所撰寫的libmylib.so 程式庫*/
handle = dlopen(“./libmylib.so”, RTLD_LAZY);
if( !handle )
{
fputs( dlerror(), stderr);
exit(1);
}
/* 取得hello function 的address */
f = dlsym(handle, “hello”);
if(( error=dlerror())!=NULL)
{
fputs(error, stderr);
exit(1);
}
/* 呼叫該function */
f();
dlclose(handle);
}
沒有留言:
張貼留言