• Linux生成动态库


    动态库

    1.命名规则

    Linux: libxxx.so

    • lib :前缀(固定的);
    • xxx:动态库的名字(自己取);
    • .so:后缀(固定的);

    Windows:libxxx.dll

    2.动态库的制作

    1. 使用 gcc 得到 .o文件 , 得到和位置无关的代码
    gcc -c -fpic a.c b.c ...
    
    • 1
    1. 使用 gcc 得到动态库:
    gcc -shared a.o b.o ... -o libxxx.so
    
    • 1

    3.示例

    我们先新建如下结构的 demo :

    在这里插入图片描述

    以上代码在博客 : Linux生成静态库

    1.使用 gcc 得到 .o文件 , 得到和位置无关的代码

    在这里插入图片描述
    此时报错显示 找不到 head.h。是因为我们没有指定头文件的路径,在命令后加上 -I ../include/ 就可以了。

    在这里插入图片描述

    2. 使用 gcc 得到动态库

    在这里插入图片描述
    将生成的动态库文件 libcal.so 移动到 lib/ 目录下。

    在这里插入图片描述

    3.生成可执行程序 app 并执行

    在这里插入图片描述
    当我们生成可执行文件 app 并执行后,报错了。

    它显示找不到这个动态库。

    执行失败的原因需要先了解 linux 加载动态库的流程和原理。

    4.工作原理

    • 静态库:gcc 在进行链接时,会把静态库中的代码打包到可执行文件中;
    • 动态库:gcc在进行链接时,动态库的代码不会被打包到可执行文件中;

    在程序启动之后,动态库会被动态加载到内存中,通过 ldd (list dynamic dependencies)命令检查动态库的依赖关系。

    那么我们要如何定位共享文件呢?

    当系统加载可执行文件的时候,能够知道其所依赖库的名字,但是还要知道这个库的绝对路径。此时就需要系统动态的载入器来获取该库的绝对路径。

    对于 elf 格式的可执行文件,是由 ld-linux.so 来完成的。它先后搜索 elf 文件的 DT_RPATH 再到 环境变量LD_LIBRAR_PATH 再到 /etc/ld.so.cache文件列表 再到 /lib/ , /usr/lib 目录,找到库文件之后将其加载到内存中。

    针对示例代码中的报错,我们先用 ldd 检测依赖关系:

    在这里插入图片描述
    我们发现系统显示 找不到 libcal.so 文件。

    由于 DT_RPATH 一般是不能改动的,所以我们可以先修改环境变量 LD_LIBRARY_PATH

    我们先获得动态库libcal.so 的绝对路径。

    在这里插入图片描述

    1.修改环境变量 LD_LIBRARY_PATH ,指对当前终端有效

    在这里插入图片描述
    此时添加了环境变量之后,app 就可以正常执行了。不过这个设置只对当前终端有效,是临时性的。

    我关闭这个终端,再新开一个终端,之前的设置都无效了。

    在这里插入图片描述

    2.修改环境变量 LD_LIBRARY_PATH ,用户级别

    修改用户家目录下的 .bashrc 文件,即 ~/.bashrc ,添加上这一句命令 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库文件的绝对路径

    在这里插入图片描述

    之后再刷新 .bashrc 文件。

    source .bashrc
    
    • 1

    再执行。

    在这里插入图片描述
    此时再新开一个终端也没问题。

    在这里插入图片描述

    3.修改环境变量 LD_LIBRARY_PATH ,系统级别

    在系统配置 /etc/profile 里面添加上那个命令 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库文件的绝对路径

    在这里插入图片描述
    保存退出之后,刷新并执行。

    在这里插入图片描述

    4.修改 /etc/ld.so.cache 文件

    由于 /etc/ld.so.cache 是一个二进制文件,无法修改。

    我们可以通过修改 /etc/ld.so.conf 来达到间接修改的目的,我们直接将 libcal.so 的绝对路径添加到 /etc/ld.so.conf 即可。

    在这里插入图片描述

    接着更新并执行,注意更新的命令是 ldconfig

    在这里插入图片描述

    5.静态库和动态库

    静态库 和 动态库的主要区别是 来自链接阶段如何处理、链接成可执行程序。分别称为静态链接方式动态链接方式

    1.静态库的制作过程

    在这里插入图片描述

    2.动态库的制作流程

    在这里插入图片描述

    3.静态库与动态库的区别

    静态库

    优点:

    • 静态库被打包到应用程序中加载速度比较快;
    • 发布程序的时候不需要提供静态库,移植方便;

    缺点:

    • 更消耗系统资源,浪费内存,可执行文件体积过于臃肿;
    • 更新、部署、发布非常麻烦;
    动态库

    优点:

    • 可以进行进程间资源共享(共享库);
    • 更新、部署、发布更为简单;
    • 可以人为的控制何时加载动态库;

    缺点:

    • 加载到内存的速度比不上静态库被打包到程序中;
    • 在发布程序时需要提供依赖的动态库;
  • 相关阅读:
    Ansible自动化运维工具(三)
    spring-retry使用介绍
    找不到工作,软件测试真的不香了?
    MySQL知识【可视化软件navicat安装&使用】第五章
    循环神经网络的网络结构,神经网络训练过程图解
    在C++项目中使用python脚本(四种)常见报错解决
    从零开始:新手快速在国产操作系统中搭建高可用K8S(V1.28)集群落地实践
    Pandas学习笔记
    【MySQL】(七)SQL约束——主键约束、非空约束、唯一约束、默认值约束、外键约束
    Fluent Bit组件同时搜集多种可观测性数据
  • 原文地址:https://blog.csdn.net/m0_74396439/article/details/134252641