zoukankan      html  css  js  c++  java
  • Linux静态动态库

    Linux静态动态库

    一、链接库的生成

    1.1、静态库的生成

    gcc -c  hello.c  			# 生成hello.o
    ar -rcs libhello.a hello.o  # 生成libhello.a
    

    1.2、动态库的生成

    //单文件动态库编译生成
     /*caculate.c文件*/
    #include "caculate.h"
    //求两个数的和
    int add(int a, int b)
    {
        return (a + b);
    }
    //减法
    int sub(int a, int b)
    {
        return (a - b);
    }
    //除法
    int div(int a, int b)
    {
        return (int)(a / b);
    }
    //乘法
    int mul(int a, int b)
    {
        return (a * b);
    }
    gcc -shared -fPIC caculate.c -o libcac.so
    
    // 多文件动态库的编译生成
    gcc -shared -fPIC fun1.o fun2.o -o libcac.so
    

    二、动态链接库的加载

    2.1、系统自动加载

    //当我们运行应用程序./a.out 一般会出现下面警告
    ./a.out: error while loading shared libraries: libmax.so: cannot open shared object file: No such file or directory
    

    出错原因:a.out运行依赖与libmax.so,而系统环境变量中找不到libmax.so。

    问题分析:
    1、Linux是通过 /etc/ld.so.cache 文件搜寻要链接的动态库的。
    2、/etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件时系统生成的

    (注意, /etc/ld.so.conf 中并不必包含 /lib 和 /usr/lib,ldconfig程序会自动搜索这两个目录)。
    

    问题解决:
    1、如果我们把 libmax.so 所在的路径添加到 /etc/ld.so.conf 中,再以root权限运行 ldconfig 程序,此时ldconfig的运行会更新 /etc/ld.so.cache 。

    2、a.out运行时扫描 /etc/ld.so.cache,就可以找到 libmax.so。

    3、但作为一个简单的测试例子,让我们改动系统的东西,似乎不太合适。还有另一种简单的方法,就是为a.out指定 LD_LIBRARY_PATH。

    2.2、动态加载

    linux提供dlopen、dlsym、dlerror和dlcolose函数获取动态链接库的函数。通过这个四个函数可以实现一个插件程序,方便程序的扩展和维护。


    共享库被分为动态链接(Dynamic linking)和动态加载(Dynamic loading)两个步骤。

    //动态链接体现在动态库的编译生成过程
    gcc -fpic -shared -o libhello.so printhellow.c 
    -fpic 	 : 指示了这是地址无关代码
    -shared	 : 指示是一个共享库
    //动态加载体现在dl库API使用,见下文。
    

    void *dlopen(const char *filename, int flag)

    dlopen()是一个强大的库函数。该函数将打开指定的动态连接库文件,并把它装入内存,加载库中的符号,并返回一个句柄给调用进程,可使用dlclose()来卸载打开的库。

    //input parameter :  @ mode
    RTLD_NOW   :立刻解析加载符号
    RTLD_LAZY  :以后需要的时解析加载符号
    RTLD_GLOBAL :允许导出符号 
    RTLD_GROUP 
    RTLD_WORLD 
    RTLD_LOCAL 
    
    //return  value
    打开错误返回NULL 
    成功,返回库引用句柄
    

    void *dlsym(void *handle, const char *symbol)

    函数功能:根据symbol(函数的名称),获取动态链接库中真实的函数地址,返回值是void*,指向函数的地址,供调用使用。

    //示例:mytest函数的实体,编译成了so动态库
    void (*pMytest)()
    pMytest = (void (*)())dlsym(pHandle, "mytest");
    

    char *dlerror(void)

    当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

    //示例程序
    #include <dlfcn.h>  
    int main(int argc, char **argv) 
    {  
        void *handle;  
        double (*cosine)(double);  
        char *error;  
      
        handle = dlopen ("libm.so", RTLD_LAZY);  
        if (!handle) {  
            fprintf (stderr, "%s ", dlerror());  
            exit(1);  
        }  
      
        cosine = dlsym(handle, "cos");  
        if ((error = dlerror()) != NULL)  {  
            fprintf (stderr, "%s ", error);  
            exit(1);  
        }  
      
        printf ("%f ", (*cosine)(2.0));  
        dlclose(handle);  
        return 0;  
    } 
    

    int dlclose(void *handle)

    1 、 dlclose用于关闭指定句柄的动态链接库,并将动态连接库从库中移除。
    2、 注意:只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

    2.3、系统加载与手动加载的区别

    A、系统加载
    1、应用程序只要已启动,动态库便加载到内存中去了,符号的解析查找,以及相关符号对应的函数调用,都是操作系统,帮我们完成。当应用程序进程结束后,可能动态库才会从内存中移除。

    2、应用程序的编译依赖与动态库: gcc -o main mian.c -lmax

    B、手动加载
    1、随应用程序的需求需要时加载,不需要时直接在程序中通过DL的API函数卸载相关的动态库,节省内存。、

    2、应用程序的编译依赖与动态库: gcc -o main mian.c ,应用程序main.c中手动加载

    附录、参考文档

    https://www.cnblogs.com/jiqingwu/p/linux_dynamic_lib_create.html

    补录、库的软链接

    关与库的链接:是连接动态还是静态的说明

    https://blog.csdn.net/abcdu1/article/details/86083295
    问题:

    问题1:-l(L的小写)链接的到底是动态库还是静态库

    答案:如果链接路径下同时有 .so 和 .a 那优先链接 .so

    问题2:如果路径下同时有静态库和动态库如何链接静态库

    答案:使用显示链接, gcc -l:lib***.a (将静态库的名字显示写出来)

    或者在 gcc 编译的时候 加入参数 -static -lXXX, 则可以添加路径下面的静态库。

    验证方法:

    可以通过 ldd 命令查看生成的 目标文件链接的库,使用方法: ldd ***.o

    ****一般情况下,连接静态库时不要使用-static 选项去链接
    https://www.cnblogs.com/lidabo/p/10245784.html

    https://blog.csdn.net/newchenxf/article/details/51743181

  • 相关阅读:
    form表单的应用
    HTML列表及表格的基本应用
    Linux上安装Jdk
    docker+jenkins自动发布步骤及命令
    redis集群部署实战
    mySQL中连接字符串
    mysql触发器
    sql 设置数字长度 不足时补0
    微服务架构特性
    SQLServer2008 去除换行符
  • 原文地址:https://www.cnblogs.com/retry/p/9983353.html
Copyright © 2011-2022 走看看