您当前的位置: 首页 >  linux

MangataTS

暂无认证

  • 0浏览

    0关注

    423博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Linux下C/C++编程开发(二)静态库和动态库

MangataTS 发布时间:2022-09-26 11:10:49 ,浏览量:0

文章目录
    • 前言
    • 一、库文件
    • 二、静态库
      • 2.1 命名规则
      • 2.2 静态库的制作
      • 2.3 静态库的使用
    • 三、动态库
      • 3.1 命名规则
      • 3.2 动态库的制作
      • 3.3 动态库的使用
        • 3.3.1 修改环境变量
        • 3.3.2 修改/etc/ld.so.cache文件列表
        • 3.3.3 /lib或/usr/lib目录
    • 四、动静态库的优缺点
      • 4.1 静态库
      • 4.2 动态库

前言

下面的所有操作的的操作都是基于:

  • 操作系统:Ubuntu20.04.3-desktop
  • GCC-Version:gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
  • G+±Version:g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
一、库文件
  • 库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
  • 库是特殊的一种程序,编写库的程序和编写一般的程序区别不大
  • 库文件有两种,静态库 和 动态库(共享库),区别是:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
  • 库的好处:代码保密 和 方便部署和分发

程序编译的过程:

在这里插入图片描述

二、静态库 2.1 命名规则
  • 对于Linux 平台的话,一般为:libxxx.a
    • lib :固定前缀
    • xxx:自定义的名称
    • .a:固定后缀

例如有一个静态库的名称:libhello.a

  • 对于Windows 平台的话,一般为:libxxx.lib
    • lib :固定前缀
    • xxx:自定义的名称
    • .lib:固定后缀
2.2 静态库的制作

静态库的制作过程: 在这里插入图片描述

制作静态库我们需要用到一个打包工具:ar (archive)

ar 可以将一些 .o 文件打包成一个 .a 静态库

使用方法如下:

ar rcs libxxx.a xxx.o xxx.o……

这里我们举一个例子:

假设我们当前有三个文件:add.cplus.chead.h

然后我们先将这两个.c文件编译、汇编成.o 文件,然后再使用ar 打包

gcc -c add.c plus.c

此时我们就会生成 add.oplus.o 文件,然后我们使用ar 命令

ar rcs libcalc.a add.o plus.o

此时我们发现生成了一个 libcalc.a 的文件,注意的是静态库代码中使用到的头文件也需要一并发送,所以我们一般将头文件集中管理,于是创建一个include 文件夹

mkdir include
mv *.h include/

同样为了方便管理静态库文件,我们也创建一个lib文件夹

mkdir lib
mv *.a lib/

此时我们的目录结构应该是这样的

在这里插入图片描述

2.3 静态库的使用

现在我们再新建一个main.c 文件,测试一下我们的这个静态库

touch main.c

然后写点简单的内容:

#include 
#include 

int main()
{
    printf("%d\n",add(1,2));
    printf("%d\n",multiply(3,4));
    return 0;
}

然后我们再编译一下:

gcc -o main main.c -I ./include -l calc -L lib

其中-l 是指定链接库的名字,而-L 表示在哪个地方去找库,-I表示的是头文件引用的位置

此时我们就生成了一个可执行程序main,我们试着运行:./main

在这里插入图片描述

这就是一个简单的静态库的打包和使用啦~

三、动态库 3.1 命名规则
  • 对于Linux 平台的话,一般为:libxxx.so
    • lib :固定前缀
    • xxx:自定义的名称
    • .so:固定后缀

例如有一个静态库的名称:libhello.a

  • 对于Windows 平台的话,一般为:libxxx.dll
    • lib :固定前缀
    • xxx:自定义的名称
    • .dll:固定后缀
3.2 动态库的制作

动态库的制作过程:

在这里插入图片描述

有了上面静态库的学习,动态库的制作其实类似,只不过编译动态库的时候全程使用gcc

步骤主要分为两步:

  • 通过 gcc 生成与位置无关的.o文件

仍然使用上面的.c文件(当然这里可以先将.o文件都删掉:rm *.o)加上-fpic 选项生成与位置无关的 .o 文件

为什么要用-fpic呢?

因为 -fpic 用于编译阶段,产生的代码没有绝对地址,全部用相对地址,这正好满足了共享库的要求,共享库被加载时地址不是固定的。如果不加-fpic ,那么生成的代码就会与位置有关,当进程使用该.so文件时都需要重定位,且会产生成该文件的副本,每个副本都不同,不同点取决于该文件代码段与数据段所映射内存的位置

gcc -c -fpic add.c plus.c -I include/
  • 通过 gcc 生成动态库
gcc -shared add.o plus.o -o libcalc.so

此时我们就生成了一个libcalc.so 的动态库文件

3.3 动态库的使用

我们将 libcalc.so 移动到 lib目录,并且删除libcalc.a静态库

mv libcalc.so ./lib
rm ./lib/libcalc.a 

此时我们的目录结构如下:

在这里插入图片描述

这个main可执行文件是上面的,我们可以先将其删除:rm main

然后我们编译main.c

gcc -o main main.c -I include -L lib -l calc

此时我们又生成了main的可执行文件

在这里插入图片描述 我们试着直接运行,会发现遇到这样的错误: ./main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory

其实就是程序运行的时候并未加载到动态库,导致了运行出错

对于动态库而言,程序启动后,动态库会被动态加载到内存中,通过 lddlist dynamic dependencies)命令检查动态库依赖关系

例如我们这里通过ldd main 来查看main 可执行文件的依赖动态库

在这里插入图片描述

我们发现此时的libcalc.so 是一个not found 的情况,所以我们需要在动态库的加载路径上将我们的libcalc.so拷贝过去

首先我们要清楚,动态库如何定位到共享文件?

当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路 径。此时就需要系统的动态载入器来获取该绝对路径。对于elf格式的可执行程序,是 由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 ——> 环境变量LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib//usr/lib目录找到库文件后将其载入内存。

流程图: 在这里插入图片描述

3.3.1 修改环境变量

新增一行数据:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/mangata/Learn_C++/Linux_study/class2/lib

LD_LIBRARY_PATH 后面跟的是动态库的绝对路径

然后在终端输入source .bashrc 激活环境变量

然后此时我们通过ldd查看main

在这里插入图片描述 就已经链接上了

3.3.2 修改/etc/ld.so.cache文件列表

因为该文件是一个二进制文件,不好直接更改,所以我们更改/ect/ld.so.conf文件,在文件末尾加上lib 的路径

在这里插入图片描述

然后出来在终端输入sudo ldconfig 使其生效

在这里插入图片描述

3.3.3 /lib或/usr/lib目录

所以我们可以将libcalc.so拷贝到/usr/lib目录

sudo cp lib/libcalc.so /usr/lib

此时我们再来通过ldd 查看main文件:

在这里插入图片描述 我们发现:libcalc.so => /lib/libcalc.so (0x00007effed09d000) 也就是说此时的动态库是能找到了

于是我们运行./main

在这里插入图片描述

四、动静态库的优缺点 4.1 静态库

优点:

  • 静态库被打包到应用程序中加载速度快
  • 发布程序无需提供静态库,移植方便

缺点:

  • 消耗系统资源,浪费内存
  • 更新、部署、发布麻烦

在这里插入图片描述

4.2 动态库

优点:

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

缺点:

  • 加载速度比静态库慢
  • 发布程序时需要提供依赖的动态库

在这里插入图片描述

关注
打赏
1665836431
查看更多评论
立即登录/注册

微信扫码登录

0.0619s