【Linux系统编程】静态库和共享库

简介: 【Linux系统编程】静态库和共享库

静态库和共享库

1. 区别

静态库

静态库在文件中静态展开,所以有多少文件就展开多少次,非常吃内存,100M 展开 100 次,就是 1G ,但是这样的好处就是静态加载的速度快。


2d1fdaa0d1344b24a1eb4dee89726d8c.png


动态库

使用动态库会将动态库加载到内存,10 个文件也只需要加载一次,然后这些文件用到库的时候临时去加载,速度慢一些,但是很省内存。



优缺点

动态库和静态库各有优劣,根据实际情况合理选用即可。

  • 静态库:对空间要求较低,而时间要求较高的核心程序中。
  • 动态库:对时间要求较低,对空间要求较高。


ee0a6234b63d4a59a138fd9375728d5d.png

2. 静态库制作

Linuxlibxxx.a

  • lib :前缀(固定)
  • xxx :库的名字,自己起
  • .a :后缀(固定)

Windowslibxxx.lib

静态库生成指令

ar rcs libmylib.a file1.o
  • r - 将文件插入备存文件中
  • c - 建立备存文件
  • s - 索引

生成步骤

第一步: 写好源代码。



第二步: 编译源代码生成 .o 文件。



第三步: 制作静态库。



第四步: 编译静态库到可执行文件中。

gcc test.c lib库名.a -o a.out


350a839ac0724e6bb262f7e671728745.png


编译时出现了函数未定义的警告,可以忽略,让系统生成默认的定义。

下图可以发现 test.c 只占用了 209 大小,而 test 却占用了 16752 ,说明静态库是直接编译到文件中。


6260fb77f29548539691657931bdb5fb.png


上面出现的警告,可以用编译器隐式声明来解决。编译器只能隐式声明返回值为 int 的函数形式:

int add(int, int);

如果函数不是返回的 int ,则隐式声明失效,所以会警告。

那我们只用在 test.c 中加入函数声明即可:


e8a9547eeda44420a7c4f6ef83243c4b.png


这时候再编译就不会警告了:


4e22c23dec2b4b189b2a20462cfee338.png


但是这样子做需要库的使用者知道库里的函数,然后再一个一个加到代码里,不是很科学,我们可以用下面这种方法来加载静态库。


2ab818527d664c978b9092ca1172e593.png


右边的 define 为头文件守卫,防止在代码中多次 include 同一个头文件,多次展开静态库,带来的额外开销。


然后我们同样进行编译,发现也不会报错,但是这样子写更好一些。


e3014eeef04d46f2871d12fe813c8303.png


当然,我们可以将静态库和头文件分别放至其他目录下,然后再模拟一遍。


a1477fbf3d454066a95abecd8c90e202.png


然后运行结果。


61473627bcec43c185b791965ad95c0b.png


3. 动态库制作

Linuxlibxxx.so

  • lib :前缀(固定)
  • xxx :库的名字,自己起
  • .so :后缀(固定)
  • Linux 下是一个可执行文件

Windowslibxxx.dll

制作步骤

  1. 1.将 .c 生成 .o 文件(生成与位置无关的代码 -fPIC
gcc -c add.c -o add.o -fPIC

使用这个参数过后,生成的函数就和位置无关,挂上 @plt 标识,等待动态绑定。

  1. 2.使用 gcc -shared 制作动态库
gcc -shared -o lib库名.so add.o sub.o div.o
  1. 3.编译可执行程序时指定所使用的动态库

-l :指定库名;-L :指定库路径

gcc test.c -o a.out -l mymath -L ./lib
  1. 4.运行可执行程序 ./a.out

过程演示

步骤一:生成位置无关的 .o 文件



步骤二:制作动态库 gcc -shared -o lib 库名 .so add.o



步骤三:编译程序

文件分布如下:动态库在 lib 目录下,头文件在 inc 目录下。



下面编译文件。



步骤四:执行文件,出错



出错原因分析:

  • 连接器:工作于链接阶段,工作时需要 -l-L
  • 动态链接器:工作于程序运行阶段,工作时需要提供动态库所在目录位置。

解决方法

(1)通过环境变量,但是临时生效

指定动态库路径并使其生效,然后再执行文件。

通过环境变量指定动态库所在位置:

export LD_LIBRARY_PATH=动态库路径

当关闭终端,再次执行 a.out 时,又报错。

这是因为,环境变量是进程的概念,关闭终端之后再打开,是两个进程,环境变量发生了变化。

(2)修改配置文件,永久生效

要想永久生效(建议写入绝对路径):

  1. 1.需要修改 bash 的配置文件:vi ~./bashrc ,写入 export LD_LIBRARY_PATH=动态库路径 并保存。
  2. 2.修改后要使配置文件立即生效:. .bashrc 或者 source .bashrc 或者重开终端让其自己加载。
  3. 3.这下再执行 a.out 就不会报错了。

(3)移动动态库(不推荐)

拷贝自定义动态库 到 /lib (标准 C 库所在目录位置)

(4)配置文件法(最难)

sudo vi /etc/ld.so.conf

② 写入动态库绝对路径保存

sudo ldconfig -v 使配置文件生效

./a.out 成功 — 使用 ldd a.out 查看

4. 工作原理

静态库: GCC 进行链接时,会把静态库中代码打包到可执行程序中。

动态库: GCC 进行链接时,动态库的代码不会打包到可执行程序中。

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

如何定位共享文件呢?

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

5. 区别




静态库



优点:

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

缺点:

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


动态库



优点:

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

缺点:

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


目录
相关文章
|
3天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
18 3
|
3天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
16 2
|
3天前
|
安全 网络协议 Linux
本文详细介绍了 Linux 系统中 ping 命令的使用方法和技巧,涵盖基本用法、高级用法、实际应用案例及注意事项。
本文详细介绍了 Linux 系统中 ping 命令的使用方法和技巧,涵盖基本用法、高级用法、实际应用案例及注意事项。通过掌握 ping 命令,读者可以轻松测试网络连通性、诊断网络问题并提升网络管理能力。
18 3
|
6天前
|
安全 Linux 数据安全/隐私保护
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。本文介绍了使用 `ls -l` 和 `stat` 命令查找文件所有者的基本方法,以及通过文件路径、通配符和结合其他命令的高级技巧。还提供了实际案例分析和注意事项,帮助读者更好地掌握这一操作。
23 6
|
6天前
|
Linux
在 Linux 系统中,`find` 命令是一个强大的文件查找工具
在 Linux 系统中,`find` 命令是一个强大的文件查找工具。本文详细介绍了 `find` 命令的基本语法、常用选项和具体应用示例,帮助用户快速掌握如何根据文件名、类型、大小、修改时间等条件查找文件,并展示了如何结合逻辑运算符、正则表达式和排除特定目录等高级用法。
31 6
|
7天前
|
机器学习/深度学习 自然语言处理 Linux
Linux 中的机器学习:Whisper——自动语音识别系统
本文介绍了先进的自动语音识别系统 Whisper 在 Linux 环境中的应用。Whisper 基于深度学习和神经网络技术,支持多语言识别,具有高准确性和实时处理能力。文章详细讲解了在 Linux 中安装、配置和使用 Whisper 的步骤,以及其在语音助手、语音识别软件等领域的应用场景。
33 5
|
7天前
|
监控 网络协议 算法
Linux内核优化:提升系统性能与稳定性的策略####
本文深入探讨了Linux操作系统内核的优化策略,旨在通过一系列技术手段和最佳实践,显著提升系统的性能、响应速度及稳定性。文章首先概述了Linux内核的核心组件及其在系统中的作用,随后详细阐述了内存管理、进程调度、文件系统优化、网络栈调整及并发控制等关键领域的优化方法。通过实际案例分析,展示了这些优化措施如何有效减少延迟、提高吞吐量,并增强系统的整体健壮性。最终,文章强调了持续监控、定期更新及合理配置对于维持Linux系统长期高效运行的重要性。 ####
|
4月前
|
Linux 编译器 vr&ar
【Linux】静态库和动态库
本文详细介绍了Linux系统中静态库和动态库的概念、区别、制作与使用方法,包括它们在链接时的区别、加载机制以及优缺点。
52 0
|
6月前
|
Linux vr&ar C语言
|
6月前
|
存储 Linux 编译器
Linux静态库与动态库的使用
Linux静态库与动态库的使用