Linux靜態庫和共享庫

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參數,表示程序運行時須要用到共享庫

 
參考:http://www.cnblogs.com/shijingjing07/p/5608104.html
相關文章
相關標籤/搜索