1.什麼是靜態庫
靜態庫相似windows中的靜態libhtml
關於windows中的靜態lib,可參考 Windows動態連接庫DLL windows
特色:包含函數代碼聲明和實現,連接後全部代碼都嵌入到宿主程序中。
只在編譯時使用,執行時再也不須要該靜態庫。函數
2.靜態庫編寫
示例以下:
addvec.c工具
void addvec(int* x, int* y, int*z, int n) { int i=0; for(; i< n;++i) z[i] = x[i] + y[i]; }
multvec.c post
void multvec(int*x, int* y, int* z, int n) { int i = 0; for(; i < n; ++i) z[i] = x[i] * y[i]; }
使用AR工具建立靜態庫文件:spa
3.靜態庫使用
示例以下:
test2.c指針
#include <stdio.h> int x[2] = {1, 2}; int y[2] = {3, 4}; int z[2]={0}; int main() { addvec(x, y, z, 2); printf("z = [%d %d]\n", z[0], z[1]); return 0; }
編譯-連接-運行程序code
1)-static參數,代表是靜態連接,編譯出的是完整的可執行目標文件。
2)當連接器進行連接時,會判斷main函數裏調用了addvec.o中的addvec函數,
沒有調用multvec.o中的任何函數,因此,連接器只會拷貝addvec.o到可執行文件。htm
4.什麼是共享庫
共享庫相似windows中的動態連接庫dllblog
特色:包含函數代碼聲明和實現。
只在運行時使用,由動態連接器連接和加載。
根據連接和加載共享庫的時機可分爲如下兩類:
1)自身加載型共享庫。
2)運行時加載型共享庫
5.自身加載型共享庫。
相似windows中的隱式連接
連接時,將共享庫的聲明信息連接到可執行文件,
應用程序加載時,動態連接庫解析聲明信息,加載共享庫的實現到存儲器,重定位應用程序中聲明信息到實際地址。
6.自身加載型共享庫使用示例
使用-shared參數,指示編譯器建立一個共享庫。
以下所示,咱們建立了一個共享庫,並經過自身加載型來使用該共享庫。
1)-fPIC參數,指示編譯器生成代碼無關的代碼
2)在連接時,沒有拷貝共享庫libvec.so的實現,只拷貝了一些重定位和符號表信息
3)程序加載時,動態連接器會解析共享庫libvec.so中代碼和數據的引用,重定位完成連接任務。
重定位libvec.so的文本和數據到存儲器段
重定位p2中引用的libvec.so到以上存儲器段
最後連接器將控制傳遞給程序,此時,共享庫的位置就固定了。
7.運行時加載型共享庫
相似windows中的顯式連接
無需編譯時連接,可在運行過程當中加載和卸載共享庫。
8.運行時加載型共享庫使用示例
Linux提供了一組運行過程當中加載和卸載共享庫的API,以下所示:
#include<dlfcn.h>
/* 加載和連接共享庫 filename filename:共享庫的名字 flag有:RTLD_LAZY, RTLD_NOW,兩者都可以和RTLD_GLOBAL表示取或 */ void *dlopen(const char *filename, int flag); // 若成功則返回執行句柄的指針,不然返回NULL /*根據共享庫操做句柄與符號,返回符號對應的地址 handle:共享庫操做句柄 symbol:須要引用的符號名字 */ void *dlsym(void *handle, char *symbol); // 若成功則返回執行符號的指針(即地址),若出錯則返回NULL /* 若是沒有程序正在使用這個共享庫,卸載該共享庫 */ int dlclose(void *handle); // 若卸載成功,則返回0,不然返回-1 /* 捕捉最近發生的錯誤 */ const char *dlerror(void); // 若前面對dlopen,dlsym或dlclose調用失敗,則返回錯誤消息,不然返回NULL
根據以上API,咱們能夠方便地加載和卸載共享庫,以下所示:
#include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int x[2] = {1, 2}; int y[2] = {3, 4}; int z[2] ={0}; int main() { void *handle; void (*addvec)(int *, int *, int *,int); char *error; handle = dlopen("./libvector.so", RTLD_LAZY); if(!handle){ fprintf(stderr, "%s\n", dlerror()); exit(1); } addvec = dlsym(handle, "addvec"); if((error = dlerror()) != NULL){ fprintf(stderr, "%s\n", dlerror()); exit(1); } addvec(x, y, z, 2); printf("z = [%d %d]\n", z[0], z[1]); if(dlclose(handle) < 0){ fprintf(stderr, "%s\n", dlerror()); exit(1); } return 0; }
運行程序:
其中,-ldl參數,表示程序運行時須要用到共享庫