• 前言
  • 0x1 什么是共享库
  • 0x2 共享库在文件系统中的位置
  • 0x3 使用 ldconfig 命令
  • 0x4 使用非标准库位置
  • 0x5 示例(如何创建一个共享库)

前言

一个库文件由多个不同的目标文件填充组成,众所周知,目标文件是由源代码经过编译得到的二进制中间文件,所以库文件中也是一系列已经编译好二进制代码,而它可能包含着在特定上下文中使用的一组函数。例如,当我们需要用到多线程中所提供的函数时, pthread 库就会被用到。

宽泛地讲,一个库(或者说程序库)有两种类型:

  • 1、共享库
  • 2、静态库

在这篇文章中我们将专门讨论共享库。


0x1 什么是共享库

一句话讲,共享库就是可以在运行时链接到任何程序的库,它们提供了一种使用加载到内存中任意位置代码的方法。一旦共享库被加载到内存,它就可以被任意数量的程序来使用。通过这种方式,大量的代码以共享库的形式被其他程序共用,所以程序本身的大小和其占用的内存都会保持在很低的状态。

共享库为开发环境提供了模块化的特性,因为库代码在修改或者重新编译后,只要其提供的接口没变,使用该库的用户程序是不需要重新编译的。例如,在修改了 pthread 库中的代码之后,使用 pthread 共享库的代码是不需要做任何修改的。

在 Linux 系统中,一个共享库通过不同的名字来访问:

  • 链接器名称lib 后面接库的名字,再接 .so 。例如 libpthread.so
  • 完全限定的sonamelib 后接库的名字,再接 .so,再接 . 和一个主版本号。例如 libpthread.so.1
  • 真实名称lib 后接库的名字,再接 .so,再接 . 和一个主版本号,再接一个 . 和次版本号,再接一个 . 和一个发布版本号,其中发布版本号是可选的。例如 libpthread.so.1.1

当共享库中代码的修改使得与之前的版本不再兼容的时候,主版本号就应该跟着改变。例如,如果一个函数被完全移除了,则需要修改主版本号生成共享库一个新的版本。

当共享库中代码的修改使得与之前的版本还是兼容的,则只需要改变次版本号。例如,修复一个小 bug 是不会破坏当前共享库的兼容性的,所以只需要改变次版本号,而主版本号保持不变即可。

现在你可能会好奇为什么一个共享库有这么多名称呢?
!!!这种命名约定帮助同一个共享库的多个版本可以在系统中共存。链接共享库的程序不需要去考虑安装在系统中最新版本的库文件,一旦共享库的最新版本被成功安装到系统中,所有的程序都可以自动地链接到最新的版本。


0x2 共享库在文件系统中的位置

在 Linux 文件系统中,主要有三个可以放置库的标准位置。

  • /lib
  • /usr/lib
  • /usr/local/lib

根据文件系统层次结构标准(FHS),所有在启动时加载并且在根文件系统中运行的库都被保存在 /lib 目录中;而系统内部使用的库存储在 /usr/lib 目录中,这些库并不是为了让用户或者 shell 脚本直接使用的;还有第三个位置 /usr/local/lib (尽管这个位置没有被定义在 FHS 的最新标准中),如果这个文件夹存在的话,那么它包含所有不属于标准发行版的库。这些非标准的库是你自己下载的库,而且它们是可能有 bug 的。


0x3 使用 ldconfig 命令

一旦一个共享库被创建出来,将其复制到相应的目录中(如 /usr/lib 或者 /usr/local/lib 中)。然后在对应的目录中运行 ldconfig 命令。那么 ldconfig 命令做了什么呢?

在之前有提到一个共享库有三种名称,链接器名称、完全限定的 soname 和真实名称。其中共享库的链接器名称是一个指向完全限定的 soname 的符号链接,而完全限定的 soname 是一个指向真实名称的符号链接。其实 ldconfig 正是干了这件事,创建符号链接。

当你运行一个 ELF 可执行文件的时候,默认情况下装载器是第一个被运行的,装载器本身也是一个共享目标文件 /lib/ld-linux.so.X,其中 .X 是一个版本号,这个装载器然后会找到并且装载所有我们程序所依赖的共享库文件。为了找到依赖库,所有装载器搜索的目录都保存在 /etc/ld.so.conf 中。搜索指定在 /etc/ld.so.conf 文件中的所有目录是非常耗时的,所以每次运行 ldconfig 命令,都会建立所需要的符号链接,然后在 /etc/ld.so.cache 文件中创建一个可执行文件所需要的所有信息的高速缓存,从缓存中读取信息可以大大减少时间消耗。但这里的问题是,每次添加或者删除共享库的时候都需要运行 ldconfig 命令,所以在程序启动的时候都会使用 /etc/ld.so.cache 去加载程序所依赖的库。


0x4 使用非标准库位置

当使用非标准库位置(即不把你的动态库安装到)的时候,可以使用以下三种方法中的一个:

1、将路径加到文件 /etc/ld.so.conf 中,该文件包含装载器搜索依赖库的所有目录的路径。
有时候这个文件可能只包含单单一行如下:

在这种情况下,只需要创建一个配置文件在同样的目录下,然后运行 ldconfig 即可。

2、通过如下命令直接添加一个目录到高速缓存文件中:

sudo ldconfig [non standard directory path containing shared library]

3、设置环境变量 LD_LIBRARY_PATH,以指向包含共享库的目录,装载器将使用此环境变量中提到的路径来解析依赖项。


0x5 示例(如何创建一个共享库)

接下来通过一个简单的示例来展示如何创建和使用共享库文件。下面是我们希望放在共享库中的代码(shared.c):

#include "shared.h"
unsigned int add(unsigned int a, unsigned int b)
{printf("\n Inside add()\n");return (a+b);
}

shared.h 如下:

#include <stdio.h>
extern unsigned int add(unsigned int a, unsigned int b);

首先我们将 shared.c 编译打包成一个共享库文件。
1、运行以下两条命令来创建一个共享库:

gcc -c -Wall -Werror -fPIC shared.c
gcc -shared -o libshared.so shared.o

第一条编译命令将源代码编译成共享库需要得位置无关代码;第二条编译命令则真正的创建了共享库 libshared.so

2、下面是使用共享库中 add 函数的用户代码

#include<stdio.h>
#include"shared.h"
int main(void)
{unsigned int a = 1;unsigned int b = 2;unsigned int result = 0;result = add(a,b);printf("\n The result is [%u]\n",result);return 0;
}

3、接下来运行如下命令:

gcc -L./ -Wall main.c -o main -lshared

这个编译命令编译 mian.c 中的代码并且告诉 gcc 去链接共享库 libshared.so 中的代码(通过使用编译选项 -l),而且告诉编译器共享库文件的位置(通过编译选项 -L)。

编译过后,可以看到当前文件夹下的文件如下:

4、如果直接运行可执行文件 main,则会报装载错误,如下:

无法找到共享库 libshared.so !!!所以接下来我们需要根据第四点中提到的那样配置路径。

当然我们可以直接将共享库 libshared.so 复制到 /usr/lib 或者 /lib 中,就不需要配置路径运行 main 了。

然后我们也可以通过增加路径配置文件到 /etc/ld.so.conf.d 文件夹下,然后运行 ldconfig命令生成缓存来完成路径配置,操作步骤如下:

当然我们也可以通过直接用 ldconfig 命令指定路径来刷新缓存,操作步骤如下:

还可以通过修改环境变量来配置路径,但是这个是临时的,关闭 shell 重启则失效了,操作步骤如下:

Linux 共享库简介(怎样创建共享库)相关推荐

  1. 【Android 高性能音频】AAudio 音频库 简介 ( AAudio 音频库简介 | 音频流 | 音频设备 | 共享模式 | 数据模式 )

    文章目录 I . AAudio 音频库 简介 II . AAudio 音频流 三要素 ( 设备 | 共享模式 | 数据格式 ) III . AAudio 音频设备 IV . AAudio 音频设备获取 ...

  2. python扩展库简介_python非官方扩展库

    flex开发小技巧集锦 关于flex开发网上有非常多的相关信息介绍,因此我们要想学习关于flex开发的知识信息技能是一件非常简单和方便的事情.而针对于flex开发小编要告诉大家的是一些flex开发小技 ...

  3. gcc创建静态库和共享库

    静态库和动态(共享)库 静态库:编译程序在编译使用库提供的功能代码的程序时将代码复制到该程序然后编译成可执行程序,这种库成为静态库 共享库:共享库比静态库的处理方式更加灵活,因而其产生的可执行文件更小 ...

  4. Head First C 第八章 静态库与动态库 创建动态库

    2019独角兽企业重金招聘Python工程师标准>>> Head First C 第八章 静态库与动态库 创建动态库 动态库是什么 静态库文件,需要在链接过程中和主程序链接在一起,如 ...

  5. Robot Framework(十四) 扩展RobotFramework框架——创建测试库

    4.1创建测试库 Robot Framework的实际测试功能由测试库提供.有许多现有的库,其中一些甚至与核心框架捆绑在一起,但仍然经常需要创建新的库.这个任务并不复杂,因为正如本章所示,Robot ...

  6. 网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页

    本文为学习笔记,整合课程内容以及下列文章: 其中,libcurl函数库常用字段解读部分: 参考博文:原文地址 作者:冬冬他哥哥 目录 Libcurl库简介 Libcurl等三方库的通用编译方法 三方库 ...

  7. Linux(信号,进程间通信)共享内存,信号量,消息队列

    信号(signal) 1.1 什么是信号? 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式 1.2 信号的来源 硬件 [1] 用户在终端按下某些键时,终端驱动程序会发送信号给前台进程 ct ...

  8. 无人机飞控 ardupilot Copter-4.0.7 库简介

    无人机飞控 ardupilot Copter-4.0.7 库简介 官方文档-库说明 核心库: 库名称 作用 AP_AHRS 使用 DCM 或 EKF 进行姿态估计 AP_Common 所有草图和库所需 ...

  9. 小白入门——Python标准库和第三方库简介

    首先简要介绍如何查看python库安装位置,常见Python标准库和常见Python第三方库简介. 查看python库安装位置 1.使用pip list查看 在cmd中输入python -m pip ...

  10. Python标准库和第三方库简介

    Python标准库和第三方库简介 先简要介绍如何查看python库安装位置,常见Python标准库和常见Python第三方库简介. 查看python库安装位置 1.使用pip list查看 在cmd中 ...

最新文章

  1. 外贸网络推广分享让网站文章标题优化效果更好地小技巧!
  2. C++调用Matlab 注意事项
  3. 手机照片导入电脑步骤_如何将手机中的照片、视频快速的保存到U盘上?3分钟教你详细步骤...
  4. 小米鼠标垫功能奇异 价格也不贵
  5. 蒙特卡洛模拟(Monte Carlo simulation)
  6. python 连接 mysql
  7. .net mysql 类库_在VBnet中连接MySql类库
  8. react前端封装接口弹出错误_react+ts打包发布后报Minified React error ..这种错误
  9. 泛微oa部署linux步骤,泛微oa部署微搜功能手册
  10. 入行自媒体怎么快速变现,详细教程,教你手把手运营
  11. 计算机无法安装MUMU模拟器,电脑手机模拟器,详细教您电脑手机模拟器MuMu模拟器怎么使用...
  12. 论文阅读笔记:Weakly-supervised Semantic Segmentation in Cityscape via Hyperspectral Image
  13. MySQL DUAL表的作用
  14. vios映射_以最低要求映射VIOS LUN
  15. MySQL~锁的大集合(S锁、X锁、意向锁、自增锁、元数据锁、记录锁、间隙锁、临键锁、全局锁、死锁)
  16. 为什么巡检在工业生产中如此重要?
  17. 机器学习 任务管理器中显示cpu占用很高,gpu很低,但是设置了Gpu运算
  18. selenium登录某宝跳过反爬监测及滑块验证
  19. Universal Serial Bus (USB) - 通用串行总线
  20. 开关电源雷击浪涌整改_开关电源之雷击浪涌大解剖

热门文章

  1. ucmap for android 使用总结
  2. 数据挖掘简单可视化方法
  3. linux etcfstab 权限,etc/fstab linux开机自动挂载
  4. Python中设置横坐标间距,进行绘图
  5. 原子物理中的组合常数 与astropy包中的科学数据
  6. raw 格式镜像的 分区 、格式化和挂载操作
  7. 趣味数模问题2-四人追逐问题(利用matlab进行模拟)
  8. 读傅献彩之《物理化学》
  9. 旧照片修复-模糊图片变清晰-2023年度最强神器 codeformer
  10. 【群智能算法】一种改进的北方苍鹰优化算法 改进北方苍鹰算法INGO[1]【Matlab代码#1】