Linux静态库与动态库学习笔记

Ubuntu下有两种库:动态库和静态库(共享库)

库的本质是可执行的二进制码,库的作用就是复用。静态库在链接期间把库文件加到主程序中,而动态库则是运行时再加载进去。

二者的不同点在于代码被载入的时刻不同。

静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。

动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

不同的应用程序如果调用相同的库,那么在内存中只需要有一份该动态库(共享库)的实例。

静态库和动态库的最大区别,静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

1、gcc工作流程 

2、gcc常用参数

-E 预处理,不会编译、汇编和链接

-S 编译,不会汇编和链接

-c 编译和汇编,但不会链接

-o 输出可执行文件

静态库


1、静态库的命名格式 
lib + 库的名字 + .a 
例:libMyTest.a (MyTest为静态库的名字)

链接期间会把库文件一起打包至可执行文件;生成可执行文件后,可以脱离环境执行;一起打包造成资源浪费

2、静态库作用分析 
在项目开发过程中,经常出现优秀代码重用现象,又或者提供给第三方功能模块却又不想让其看到源代码,这些时候,通常的做法是将代码封装成库或者框架,生成的静态库要和头文件同时发布。

优点:寻址方便,速度快
库在链接时被打包到可执行文件中,直接发布可执行程序即可以使用
缺点:静态库的代码被加载到可执行程序中,因此体积过大
如果静态库的函数发生改变,必须重新编译可执行程序


3、静态库的制作与使用

测试代码的目录结构如上图所示,include中存放的是头文件,libs中存放的是静态(动态)库,res中存放的是源代码,main.c是发布代码。

第一步:把res目录下的.c文件生成.o文件:

gcc *.c -c

第二步:把.o打包成静态库,并移动到libs目录:

ar rcs libMyTest.a *.o        将所有.o文件打包为静态库,r将文件插入静态库中,c创建静态库,不管库是否存在,s写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。
mv libMyTest.a ../lib         将静态库文件放置lib文件夹下
nm libMyTest.a                查看库中包含的函数等信息

第三步:在主目录下链接生成可执行文件

gcc main.c -Iinclude -Llibs -lMyTest -o app

该可执行文件是可以脱离环境执行的,把其移到桌面,执行正常。

动态库(共享库)


1、动态库的命名格式 
lib + 库的名字 + .so 
例:libMyTest.so (MyTest为动态库的名字)

2、动态库作用分析 
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

优点:

节省内存
易于更新,不用重新编译可执行程序,运行时自动加载
缺点:

延时绑定,速度略慢

动态库存在是为了解决静态库的某些问题:静态库和主程序一起打包成可执行文件,造成程序包变大;静态库在更新时,需要重新编译生成可执行文件,而动态库是程序运行时加载的,只需把动态库修改则可。

3、动态库的制作与使用

测试代码的目录结构与静态库相同。

第一步:在res目录下,生成和位置无关的代码:

gcc -fPIC *.c -c   参数-fPIC表示生成与位置无关代码

第二步:创建动态库

gcc -shared -o libadd.so *.o        参数:-shared 制作动态库 -o:重命名生成的新文件
mv libMyTest.so ../lib
第三步:使用动态库,在主目录下生成可执行文件:

gcc main.c -Iinclude -Llibs -ladd -o app

尝试执行该文件,发现找不到.so

证明动态库和静态库的链接是不一样的。那么如何运行该程序呢?

使用命令ldd app可以查看当前的链接库情况;

链接动态库有4种方法:

第一种方法:

把动态库路径加到环境变量:添加完后,执行成功

export LD_LIBRARY_PATH=//动态库的绝对路径(只能起到临时作用,关闭终端后失效)
LD_LIBRARY_PATH : 指定查找共享库(动态链接库)时除了默认路径之外的其他路径,该路径在默认路径之前查找

第二种方法:

打开home目录下的.bashrc文件,将上述命令写入,即上面所说的动态库的绝对路径,保存后重启终端生效(永久)

第三种方法:
直接将动态库拷贝到user/lib的系统目录下(强烈不推荐!!)

第四种方法:

配置动态库链接器的配置文件:
将libmytest.so所在绝对路径追加入到/etc/ld.so.conf文件,使用sudo ldconfig -v 更新。

原创文章 96 获赞 48 访问量 6万+

猜你喜欢

转载自blog.csdn.net/wteruiycbqqvwt/article/details/103538189