【Linux】动态库|静态库|创建使用|动态库加载过程

 

目录

​编辑

前言

 静态库

为什么要使用库(形成原理 )

 生成一个静态库

静态库的使用

动态库

生成一个动态库

动态库的使用

解决方法

动态库加载过程

​编辑


前言

库(Library)是一种方式,可以将代码打包成可重用的格式(站在巨人的肩膀上),供其他程序调用。

库可以分为静态库(StaticLibraries)和动态库(Dynamic Libraries 或 Shared Libraries)

  • 动态库:库文件,以.so为后缀(Windows中为.dll)
  • 静态库:库文件,以.a为后缀(Windows中为.lib)

库的命名规则:lib库名.后缀
所以掐头去尾才是它的库名。使用gcc进行编译的时候,默认是采用的动态链接,如果要使用静态链接需要加上选项-static

libc.a            libstdc++.so.6

所以这两个库名分别为cstdc++

库中的内容都是一些被编译过但是还未被链接的目标文件(以.o或者.obj结尾的二进制文件)。

 静态库

静态库在程序编译链接的时候将库的代码整合复制到可执行文件中的代码和数据中,生成的可执行程序在运行时将不再需要静态库,因此使用静态库生成的程序大小比较大;

为什么要使用库(形成原理 )

  • 当我们需要程序功能提供给别人时,但又不想直接给出源码,我们可以将源文件汇编成二进制文件(二进制文件不会暴露源码)后,将头文件和二进制文件目标文件交给别人;
  • 不仅如此,日常中将常用功能打包成库也可以提高效率

 生成一个静态库

ar -rc 生成库的名字 源文件...

ar 命令是 gnu 的归档工具,常用于将目标文件打包为静态库,ar(archive)

  • -r (replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件
  • -c (create):建立静态库文件

 一般静态库是以.a为后缀

以一个简单的运算为例

将函数定义的.c文件编译成二进制文件   

 

使用ar命令,将这些二进制文件打包成静态库

静态库的使用

前面我们创建了一个简单的静态库;

当我们的程序依赖某个静态库时,链接器(linker)会将库中的相关文件整合到可执行文件中(前面提过),我们的test.c文件依赖库中的sub,sum函数,如果不链接库,只能一个个链接源文件

而现在我们已经将所需的函数打包成了静态库libmymath.a;
考虑使用以下指令:

gcc -o test.exe test.c -I ./mymath/include/ -L ./mymath/lib/ -lmymath

注:

  • 编译器不知道所包含的头文件.h在哪,所以需要我们指定头文件的搜索路径;
  • 头文件中只有函数的声明,没有函数定义,所以需要我们指定所要链接库文件的搜索路径;
  • 编译器也不知道需要链接的库在哪里,是哪一个库,这还需要我们指定路径;因为库目录下可能有很多库文件;
  • 平时所写的C/C++不需要这些选项可以直接编译,是因为我们写的库不在系统默认路径下;
  • -I:指定头文件搜索路径(大写的i)
  • -L:指定库文件搜索路径
  • -l:指明需要链接库文件路径下的哪一个库(L的小写)

生成的文件很大,因为链接静态库后,该库中的所有数据和代码都存在可执行文件中,所以后续将静态库删除也不会影响程序的执行;​​​​

file查看文件 

 

可以看到描述,我提供的明明是静态库,为什么是动态链接 

  • gcc 默认是动态链接的(建议行为),对于特定的一个库,究竟是动态链接还是静态链接,取决于你提供的是动态库还是静态库
  • 一个可执行性程序不可能只依赖一个库函数,也就是说必须依赖多个库函数
  • 但是,假设动静态库同时给你,编译器只能把静态库拷贝到可执行程序里面,然后只能进行动态链接,哪怕只有一个动态库剩下的全是静态库,链接依旧是动态链接
  • 全部提供的是动态库,链接也是动态链接;提供有指定的静态库,再以静态的方式编译,这样链接就是静态链接

动态库

  • 动态库(Dynamic Libraries)能够使多个程序共享同一份库代码,而不需要将这些代码复制到每个程序的可执行文件中,从而节省系统资源并便于维护和更新。 
  • 与静态库不同的是,动态库被链接后存在于进程的共享区域内,该区域内的数据和代码可以供多个进程使用。也就意味着,如果我们在生成可执行文件之后,将动态库删除,程序便会报链接错误。这是和使用静态库不一样的地方。

生成一个动态库

gcc -fPIC -c sub.c
gcc -fPIC -c sum.c

选项 -fPIC:表示生成位置无关码。

  • 位置无关码的意思就是,生成的代码在内存中可以被加载到任何位置,而不是某个固定的地址。这种特性对于动态库尤其重要,因为动态库需要能够被多个不同的程序共享,并且每个程序可能将库加载到不同的地址空间。位置无关码的寻址方式为相对寻址,可以将代码中的所有指针认为是一个个偏移量,不同的程序给与它不同的初始地址,这样就能灵活的将库加载到其它的地方。

生成动态库时我们不必使用ar命令,使用 gcc 生成动态库即可,多加了一个选项 -shared 

选项 -shared 表示 链接器 生成一个动态库而不是默认的可执行文件。生成的动态库文件以.so结尾。

动态库的使用

  • 动态库是在运行时被访问的, 编译器能指定路径能找到动态库,不代表操作系统能找到;
  • 静态库没有这样的问题是因为它是一次性工程,在链接阶段将所有的代码和数据都拷贝到程序内部了;
  • 对于一个动态库,链接时要告诉编译器自己在哪,运行时要告诉操作系统在哪;

解决方法

  • 安装到系统:
    • 将我们自己的动态库拷贝到/lib里面,就能成功运行了:
  • 建立软链接:
    • 在/lib目录下建立软连接
  • 命令行导入环境变量:
    • 修改动态库默认路径的环境变量LD_LIBRARY_PATH:
    • export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
      • 其中/usr/local/lib表示库路径
  • 修改.bashrc配置文件,让环境变量永久生效 
    • 找到LD_LIBRARY_PATH配置项,并在其路径下添加库的路径,这样每次登录都会自动生效。
      如果你发现你的./bashrc没有LD_LIBRARY_PATH那你可以自己手动加一个环境变量LD_LIBRARY_PATH过去:export LD_LIBRARY_PATH=/path/to/your/libs:$LD_LIBRARY_PATH

动态库加载过程

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值