Linux 库文件浅谈(C语言)

前言:

在讲解Linux下库文件的知识之前,请先来简单了解一下C语言程序的编译过程。

预处理
编译
汇编
链接`lib库文件`
a.c / b.c / ...
a.i / b.i / ...
a.s / b.s / ...
a.o / b.o / ...
example 可执行文件

在Linux系统gcc编译器下,C语言程序的编译过程基本可分为预处理编译汇编链接四个过程。

其中,最后一步的链接,就是将系统的库文件(或是程序员自己编写的库文件)与经过汇编步骤生成的所有.o文件(可重定位文件1)合并生成最后的example可执行文件。库文件的使用也主要与此部分有关。


Linux 下库文件简介

1. 库文件是什么?

由以上C语言编译过程可以知道,编译最后要生成可执行文件example,必须去链接一些所谓的“库文件”,那这些神秘的库文件又是什么呢?

其实,库文件就是包含一系列子程序的集合体,也可以简单理解为一堆.o文件的打包集合。在库文件中封装了一系列函数的实现,而调用者通过加载库文件就可以实现对库中的函数的调用。(注:根据实现和使用方式的不同又可分为静态库和动态库,后面会详细介绍;编译过程默认链接系统标准C库和gcc内置库,外部库需手动链接

一方面,对库文件的灵活使用可以使得编程更加便捷、高效。另一方面,对库的使用也更好的保证了部分程序源码的私密性(如某个函数中包含了重要的算法,而你又不想公开这个算法,那么便可以将其编入库中)。同时,使用库文件还可以减少重复编译的时间,增强程序的模块化。

2. 静态库与动态库的区别

静态库与动态库二者之间最大的不同点在于代码被载入的时刻不同。静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。而动态库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

静态库动态库
在程序编译阶段载入程序在程序运行阶段动态加载
使得可运行程序体积较大可运行程序体积基本不变
程序的运行不依赖于库,一次编译,永久有效,运行效率较高程序的运行依赖于库,需动态加载,运行效率较低
浪费大量储存空间节省大量储存空间
程序编译阶段载入程序,无法进行后期的维护和升级程序运行阶段动态加载,与程序耦合性较低,方便进行后期的维护和升级

静态库与动态库各有利弊,但由于动态库更加方便进行后期的维护和升级,动态库在实际项目中更加常用。


Linux 下库文件制作

假设有两个文件 a.cb.c,下面我们分别将它们制作成静态库libxxx.a和动态库libxxx.soxxx为库的随意名字,静态库和动态库名称不一定要相同)。

1. 制作.o文件:

gcc a.c -o a.o -c -fPIC
gcc b.c -o b.o -c -fPIC

由此得到文件 a.ob.o

2. 制作静态库:

ar rcs libxxx.a a.o b.o

由此得到静态库libxxx.a

3. 制作动态库:

gcc a.o b.o -o libxxx.so -shared -fPIC

由此得到动态库libxxx.so


Linux 下库文件的使用

1. 编译时库的使用

gcc example.c -o example -L dir/ -lxxx

备注

  1. dir/ 中存放库中函数声明的头文件
  2. 除去前缀后缀之外的,如libxxx.a,库名就是xxx
  3. 当同一个目录下,有重名的动态、静态库,默认情况下会自动链接动态库,如果要指定静态库:
gcc example.c -o exmaple -L dir/ -lxxx -static

2. 运行时库的使用

静态库由于在程序编译阶段就已经编入了程序中,因此运行时就不再需要,而动态库则需要动态链接。

动态库链接的3种方法

  1. 设置环境变量 LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:dir/ 

注:dir/ 就是动态库的所在路径,也可以将命令写入系统配置文件使其永久生效。

  1. 将库文件,放入系统的标准库路径中:
/lib
/usr/lib
/usr/local/lib
...

注:避免使用这种方法,污染了系统!

  1. 在编译的阶段,告诉程序以后动态库会放在哪里:

告诉程序 example,运行时动态库的路径就在 dir/ 里面

gcc example.c -o example -L . -lxxx -Wl,-rpath=dir/

此篇文章仅供大家参考学习,内容较为浅显,如有不足之处,还请见谅!


  1. 所谓的可重定位,指的是该文件虽然已经包含可以让处理器直接运行的指令流,但是程序中所有的全局符号(函数和全局变量)尚未定位,地址仍为0,程序无法正确运行。该文件中所调用的函数或是全局变量的声明可能不在此文件中,需要结合其他文件中的信息才能重新定位此函数或是变量地址,程序才能正确运行。 ↩︎

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值