动/静态库
三种时间
之前Linux指令操作的博客中有提到过可以通过stat命令查看文件/目录的属性信息,其中有3种时间分别是Access、Modify以及Change时间,这三种时间有什么区别呢?
Access
Access为最后访问时间,但是在较新的Linux内核中,Access时间不会被立即更新,而是有一定的时间间隔,操作系统才会自动进行更新时间。
Modify
Modify为最近一次修改文件内容的时间
Change
Change为最近一次修改文件属性(权限)的时间,在修改文件内容的时候,有可能修改文件的属性,比如在更改文件内容的时候文件大小属性发生修改。
应用
那么这些时间有什么用呢?要知道在使用Makefile产生可执行文件时,是否能连续进行多次make操作呢?并不能,系统会提示已经更新到最新版本了,他正是依据可执行文件和源文件的时间新旧,从而指导系统哪些源文件需要编译。另外touch命令除了创建普通文件以外,还可以起到更新文件的作用。
动/静态库
动/静态库概念
静态库一般是以.a结尾,他程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
动态库一般是以.so结尾,程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
库的命名
查看可执行程序使用的动态库可以使用ldd+可执行文件,例如:
库文件的名称是lib + 真实名称 +后缀,其中中间的内容也就是lib和后缀之间的部分是库真正的名字。
动静态链接
gcc进行编译链接默认有两种方式,动态链接和静态链接,如下所示,查看方式为file+可执行文件名。这里有一点可以注意一下就是gcc一般默认使用的是动态链接,静态链接需要在Makefile中加上static选项。
这里可以看到静态库在使用ldd查看使用的动态库文件时确实没有显示出来。
库的内容
一套完整的库往往包含了库文件本身,头文件(会说明库中暴露出来的方法的基本使用),以及说明文档。
可执行程序只需要.o链接就可以使用,将所有.o文件打包也就是库。C/C++在编译形成可执行文件的时候,我们一般会将声明和定义分离,在.h文件中放入声明,在.c文件中放入实现,但是如果我们不想让别人看到具体实现的细节,那么就可以给别人制作好的库,其中只包含.o文件即可。
生成静态库
使用如下代码即可编译形成一个静态库,其中ar命令是gnu归档工具类似于打包,打包形成静态库,-rc命令是replace和creat的意思,创建静态库。第二段的%.o"%.c是将所有的.c文件生成.o文件,最后的output选项则是将.h文件和库文件打包进入创建的output文件夹中(这里图片中最后的*.o应该是.h文件)。
其中ar还有-tv选项来查看静态库。
静态库的使用
安装库的命令
我们可以使用如下代码,将我们自己的库文件以及头文件放入系统的路径中,这样就能像我们正常使用C语言的各种库函数来使用我们制作的库,但是不推荐这种方法,因为这种方法可能会和系统中原有的库文件产生冲突甚至替换了系统原有的文件。
这就是为什么之前的代码中的库不需要指明这些选项,因为之前的库在系统的默认路径下 /lib64,/usr/lib,/usr/include等编译器使能识别这些路径的。
指定库文件
我们可以在编译链接的时候加上相关选项,指定我们所使用的库,例如:
其中-I 后面加头文件所在路径 -L 后面指定库文件所在目录 -l后面加库名称(真实名称),指明要连接哪个库。
制作动态库
其中,-shared选项是形成一个动态链接的共享库
-fPIC选项是产生目标文件,程序内部地址方案与位置无关。
后面output选项和静态库一样。
动态库使用方法
编译时给出路径
这里只是告知编译器头文件库路径在哪里,当程序编译好的时候已经和编译器无关了,运行的时候需要告知加载器我们的库在哪里,该方法和静态库的方法类似。
设置环境变量
LD_LIBRARY_PATH环境变量:指明程序启动之后,库的搜索路径,将库的路径加载到环境变量中
设置系统路径
拷贝.so文件到系统共享库路径下, 一般指/usr/lib,方法和上面静态库类似。
设置配置文件
配置/etc/ld.so.conf.d/,ldconfig更新,每次操作之后需要更新ldconfig更新配置设置
具体操作如下:
在/etc/ld.so.conf.d/路径下新建一个.conf的配置文件,在其中输入库文件所在路径,然后保存退出,再使用ldconfig更新配置
接下来编译形成的可执行文件中,就可以使用自己设置的库了。
后面删除自己的配置文件后就无法使用该库了,这里需要注意的是删除操作以后也需要进行更新配置文件的操作。
这种设置配置文件的方式可以使该库永久生效,即本次退出后下次登录依然可以使用,所以使用该方法时需要谨慎选择。