[Linux系统编程] 静态库与动态库

一.库的概念

库是写好的现有的,成熟的,可以复用的代码。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。
静态链接: 库随着程序一起编译,成为可执行程序的一部分,空间开销大,运行速度快
动态链接: 库只有在程序执行时被用到时才会被加入到内存中,空间开销小,运行较慢

二.Linux环境下静态库的制作及使用

首先使用-c选项,将c文件编译为二进制文件(.o),然后使用ar工具将二进制文件制作为静态库。

ar rcs [libXXXX.a] [所用到的.o文件]
其中,库文件名字XXXX可随意编写,但必须以lib为开头,.a为结尾

在这里插入图片描述
在第二步创建静态库的过程中:

使用gcc编译c文件时,使用ar rcs
使用g++编译cpp文件时,使用 ar qcs

使用静态库的过程中,使用gcc编译c文件时,需要加上静态库的存储目录以及名称。
静态库使用,是将静态库实际编译至可执行文件。
如 : gcc test.c ./lib/libtest.a

注意:
源文件中必须要有函数的定义才可正常编译,若在源文件中没有包含库文件中的函数定义,系统会为其自动隐式定义,可正常执行,但会报错,使用-Wall选项可以查看有报错信息
所以在使用静态库的时候,一般都会在源文件中包含一个头文件,内部是所有的静态库函数定义。
在头文件中,要包含一个头文件守卫,防止重定义。

在这里插入图片描述

总结使用过程:
gcc [c文件] [库文件目录及名称] -I [头文件目录] -o [可执行文件命名]
如:gcc test.c ./a/libmymath.a -I ./b/ -o test.exe

gcc中选项:

-I 指定头文件目录
-o 指定文件名称
-Wall 查看报错信息
-g 增加调试语句
-c 只做预处理,编译,汇编操作,得到二进制文件,不进行连接操作。

三.Linux环境下动态库的制作及使用

第一步:
与静态库制作不同,在生成二进制文件(.o)时,需要生成与位置无关的代码,使用选项**-fPIC来实现。
原因:因为动态库是在程序运行时加载进入内存,其内部函数的地址绑定时间晚于源文件函数,只有动态库加载进入内存时,这些函数才有确切的地址(地址回填),而源文件中定义的函数在链接后就已经绑定地址。
第二步:
制作动态库,使用
gcc -shared -o [库名] [二进制文件]**
第三步:
使用动态库时,与静态链接不同,不会把动态库编译进入可执行文件,但需要指定库
-l 指定库名(去掉前缀lib 和 后缀so)
-L 指定目录
gcc [执行文件] -l [库名] -L [目录地址]
第四步:
此时的可执行文件还不可运行,这是因为动态链接器还无法工作,动态链接器需要找到库的存放目录,通过配置环境变量LD_LIBRARY_PATH 来指定。
执行一次环境变量的配置,在下次启动终端时不在生效,也就是临时生效。
为了解决这个问题,可修改.bashrc配置文件,加入如下语句,可以实现启动时自动读取库目录。
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

四.链接过程中的地址回填和数据段合并

1.什么是地址回填?
上文讲动态库链接时,动态库函数的地址会晚于源文件中函数的地址绑定,它们是在动态库加载进入内存后才进行绑定的,在加载入内存后,进行动态链接时会进行这个操作,被称为地址回填。
2.什么是数据段合并
其目的就是为了减少内存开销。
在Linux系统中,内存分页管理,一个页面多数为4K或8K

如下内存图中的可改数据段和不可改数据段,如果它们被分配的页面大小超过它们本身的所需要存储大小,就会降低内存的利用率。于是可以将某些数据段合并,用于增大内存利用率。这就是数据段合并。
在这里插入图片描述

GCC编译过程:

在这里插入图片描述程序中头文件与源文件不在同一目录下,需要使用gcc -I 指定头文件目录位置

在这里插入图片描述
使用C++ 11新标准时,需要加 -std=c++11
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值