linux系统:共享库概念以及创建步骤总结

本文深入探讨Linux系统中共享库的概念,包括静态库与动态库的特点、创建步骤、使用方法及命名规范。详解如何通过静态链接与动态链接实现库文件的高效利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux系统:共享库概念以及创建步骤总结

1.1 静态库
  • 静态库也称为归档文件,可以理解为一组常用的目标文件被存放在一起,然后打了一个包,在链接阶段,连接器LD会自动链接该库文件
    1. 静态库的名字格式:libname.a
    2. ar -r 库名字 目标文件1 目标文件2:将目标文件添加到库中,并且替换掉相同名字的目标文件
    3. ar -tv 库名字:查看库中所有目标文件的详细信息
    4. ar -d 库名字 目标文件:从库中删除目标文件这个模块
  • 使用静态库:
    1. 把静态库放在链接器会搜索的标准目录中(如/usr/lib),然后执行编译命令的时候加上-l并且指定库名字,如下:
      • gcc demo.c -lname
    2. 如果没有放在可以搜索到的目录,可以用-L加上目录名字
      • gcc demo.c -lname -L目录名字
    3. 一个静态库中可以包含很多模块,但是链接器只会链接需要的模块
  • 特点:
    1. 移植方便:因为程序运行期间不用再关心库的问题,链接的时候已经做好了
    2. 浪费空间:所有需要的静态库中的目标文件会链接到可执行文件中,增加可执行文件的大小
1.2 动态库
  • 特点:
    1. 目标模块被多个程序共享
    2. 目标模块不会被复制到可执行文件中
    3. 第一个程序运行时候,会加载目标模块的副本进入内存中,之后其它程序也可以在这片内存中使用该目标模块
    4. 每个进程共享目标模块的代码,但是不会共享变量
1.2.1 使用一个共享库
  • 如果要使用一个共享库需要做两件事情:
    1. 链接阶段将共享库的名称嵌入到可执行文件中
    2. 运行程序时候,解析库名,找到对应库文件,如果不在内存就加载进内存
  • root@ubuntu:/lib# gcc -g -Wall -o prog prog.c libfoo.so
    1. 将程序和共享库链接起来就会把其库名字加入到可执行文件中,这个阶段称为静态链接阶段
    2. 但是这个时候执行./prog 文件会报错,这个阶段称为动态链接阶段,因为动态链接器LD在标准路径(/lib/等)找不到库文件,因为库文件存在于当前目录
      • 解决办法:LD_LIBRARY_PATH 环境变量也是LD搜索的范围,只需要执行的时候LD_LIBRARY_PATH=. ./prog 就不会报错了
1.2.2 共享库别名soname
  • 我们可以给共享库起一个别名,然后嵌入到可执行文件中的名字就是别名soname,而不是真实库名,这是为了提供一个间接层,当库的版本太多的时候,起到很好的作用

  • 创建一个共享库,起别名的方式,并和一个程序链接起来:

在这里插入图片描述

  • 把共享库加载进内存的过程:

    在这里插入图片描述

  • LDD 可执行文件:可以看到可执行文件中包含哪些库,显示格式library-name > 库路径

1.2.3 共享库命名规范
  • 库文件命名:libname.so.major-id.minor-id.补丁号

    1. major-id:主要版本号,表示不同的库版本,修改库某些东西之后,不在相互兼容
    2. minor-id:次要版本号,如果主要版本号相同,次要版本号不同,表示相互兼容,只是更新了一些东西
  • soname命名:libname.so.major-id

  • 连接器名称:libname.so

  • 这三个名称最好都放在同一个目录下面,这是规范

    在这里插入图片描述

  • 然后我们来想想,为啥需要soname和链接器名称,如果只用库的真实名称,不同库版本,我们都需要在链接的时候把库名字加在编译命令后面,这不是麻烦吗?所以我们用soname一直指向库的最新次要版本,然后我们在用一个链接器名称指向soname,这个时候编译的时候,我们就可以加上-lname选择,然后编译器自己会在相应的目录中的去寻找库文件,把soname嵌入到可执行文件中。同时如果就算出现了新的次要版本库文件,我们可以通过使用ldconfig命令来更新,然后就会自动让soname指向最新的次要库文件了,但是出现了新的主要版本库,需要认为改变链接器名称的指向

在这里插入图片描述

1.3 安装共享库
  • 正规情况我们应该把库放在标准目录下:

    在这里插入图片描述

  • ldconfig会先后搜索/etc/ld.so.conf中指定的目录、/lib、/usr/lib,然后为每个最新的库文件创建soname或者更新soname,最后在生成一个/etc/ld.so.cache缓存,其中保存了每个库的主要版本的最新次要版本,ldconfig -p可以查看/etc/ld.so.cache文件

  • ldconfig -nv .:处理当前文件下的库文件,不需要更新缓存文件/etc/ld.so.cache

  • 程序运行期间我们也可以更新库文件,通过ldconfig刷新之后,如果更新的是主版本,我们需要重新为链接器名称指定最新的soname,然后程序终止或者重启的时候会调用新库

  • 动态连接器查找库文件的步骤:

    在这里插入图片描述

  • 如果系统上存在libname.so和libname.a,默认会优先链接动态库libname.so,如果非要链接静态版本,就需要加上-static命令

  • 大家可能会好奇,标准C库在链接的时候,可以不用加上-lname命令了,因为标准C库按照一定的规则,会让编译器和连接器自动去查找,而三方库和我们自己写的库,则需要我们加上-lname选择

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值