在举例之前,先做两个demo,mymath.h mymath.c myprint.h myprint.c(这些代码打包成库)
mytest.c尝试调用静态库和动态库
一:静态库的生成
我们在生成静态库时,需要使用ar工具,并且需要通过gcc指令生成xxx.o文件,最终,将生成的库和头文件打包放在文件夹中(都是必要要用的)。
tips:gcc -(e,s,c) 分别对应(xxx.i,xxx.s,xxx.o)
ar -rc(运行生成静态库) ar -tv(列出库中所有文件)
二:静态库使用
静态库的使用除了在代码中包含xxx.h头文件之外,最主要的是在编译时在makefile中的代码要有相关连接选项
其中,-I(include),-L(link),-l(xxx ) ,且调用库时,用的名字需要去除libxxx.a前面的lib和.a以及之后的后缀)
当然,你也可以把这些头文件和库放在系统盘下,这样之后只需要 -lxxx选项就可以了
三:动态库制作
动态库的制作和静态库的制作大同小异,同样需要xxx.o的文件,但是这里生成的xxx.o文件方式和静态库不太一样 ,gcc -c的选项之中多了-fPIC选项,代表产生的代码没有绝对地址,完全采用相对地址,所以代码可以被加载到任意区域。
gcc -share选项代表生成动态库 。
四:动态库使用
动态库的使用和静态库相比会稍微多一些步骤,下面我们分两步解释:
1.makefile的代码
到了这一步之后,我们如果直接运行mytest,那么大概率会出现报错,莫慌,这是正常现象
2.动态库链接
为什么我们的可执行程序会运行不起来呢,因为,我们在gcc编译的时候,我们把文件的路径都告诉了gcc编译器,但是在可执行文件运行的时候,它是一个进程,它哪知道要去哪找链接的库啊
所以为了让我们的可执行文件快的的跑起来,我们有如下三种方案,各位看官可以随意选一种
方案1:
我们可以在LD_LIBRARY_PATH里添加静态库的路径,但是美中不足的是,当我们重新启动之后,我们添加进去的路径就无了。
添加方式:
冒号后面的xxx代表你的动态库的路径,不是头文件的路径 !!!
方案2(推荐):
在我们的linux下有若干的.conf文件,这些文件内部其实都是记录了各种需要连接的地址,我们只需要手动添加一个.conf文件就可以了,该方法可以永久有效
具体操作如下:
step1.创建/etc/ld.so.conf.d/路径下的conf文件
step2:通过vim添加动态库路径,这步需要sudo 权限
在vim里添加自己动态库路径
step3:输入以下指令加载新添加的.conf文件
方案三:
我们也可以选择最省事的且是永久使用的方案,创建软连接
然后再运行就不会报错咯。
五:理论篇
那么问题来了,为什么静态库加载到可执行文件里面,最后可以直接运行,动态库生成可执行文件之后,执行还这么拧巴呢?
原理是这样的,静态库在生成可执行文件的时候,库里的代码已经编译进了可执行文件内,就相当于是有了个人所有的东西。而动态库就像是共享单车,就一份,哪里要用就过来”借“。
(图画的略丑,大家不要介意)
每次当我们需要动态库的时候,我们的动态库在磁盘上被加载进物理内存(此时和地址无关),随后根据页表映射,动态库对于可执行文件的进程而言变得”可见“,在需要用到库的时候会跑过去执行库中的代码。执行完之后再返回执行自己的代码。
简言之,就是在自己的地址空间中,可以执行自己和库的代码。