zoukankan      html  css  js  c++  java
  • Linux静态库和共享库【转】

    转自:http://www.cnblogs.com/zlcxbb/p/6806269.html

    1.什么是静态库

    静态库类似windows中的静态lib

    关于windows中的静态lib,可参考 Windows动态链接库DLL 

    特点:包含函数代码声明和实现,链接后所有代码都嵌入到宿主程序中。
    只在编译时使用,执行时不再需要该静态库。

    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 

    复制代码
    void multvec(int*x, int* y, int*  z, int n)  
    {  
         int i = 0;  
         for(; i < n; ++i)  
              z[i] = x[i] * y[i];  
    }
    复制代码

    使用AR工具创建静态库文件:

    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]
    ", z[0], z[1]);  
        return 0;  
    }
    复制代码

    编译-链接-运行程序

    1)-static参数,表明是静态链接,编译出的是完整的可执行目标文件。
    2)当链接器进行链接时,会判断main函数里调用了addvec.o中的addvec函数,
    没有调用multvec.o中的任何函数,所以,链接器只会拷贝addvec.o到可执行文件。

    4.什么是共享库
    共享库类似windows中的动态链接库dll

    特点:包含函数代码声明和实现。
    只在运行时使用,由动态链接器链接和加载。

    根据链接和加载共享库的时机可分为以下两类:
    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
    ", dlerror());  
            exit(1);  
        }  
      
        addvec = dlsym(handle, "addvec");  
        if((error = dlerror()) != NULL){  
            fprintf(stderr, "%s
    ", dlerror());  
            exit(1);  
        }  
      
        addvec(x, y, z, 2);  
        printf("z = [%d %d]
    ", z[0], z[1]);  
      
        if(dlclose(handle) < 0){  
            fprintf(stderr, "%s
    ", dlerror());  
            exit(1);  
        }  
      
        return 0;  
    }  
    复制代码

    运行程序:

    其中,-ldl参数,表示程序运行时需要用到共享库

    参考:http://www.cnblogs.com/shijingjing07/p/5608104.html
  • 相关阅读:
    内存对齐
    两篇很好的EPG相关文章
    探索Linux通用SCSI驱动器
    Eclipse如何打开Android工程
    android应用程序源码结构分析
    传智播客学习之Android运行原理 (转)
    AndroidManifest.xml文件详解
    利用Java泛型实现简单的泛型方法
    二分查找之Java实现
    STM32F10x的启动汇编分析
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/7655109.html
Copyright © 2011-2022 走看看