动静态库
- 1. 见一见动静态库
- 2. 动静态库概念
- 2.1 为什么要有动静态库
- 2.2 定义
- 3. 写一写——库的设计角度
- 打包成静态库
- 打包成动态库
- 4. 用一用——使用者角度
- 4.1 直接使用头文件和源文件(直接给源代码)
- 4.2 得到头文件和源文件进过处理后形成的二进制文件.o
- 4.3 得到头文件和静态库
- 4.4 得到静态库的压缩包
- 4.5 将头文件和静态库文件安装到系统路径下
- 4.6 得到动态库
- 总结第三方库的使用关键
- 5. 动态库的配置与使用
- 5.1 配置环境变量LD_LIBRARY_PATH(临时方案)
- 5.2 在系统库路径下建立动态库的软链接
- 5.3 配置文件方案
- 6. 动态库的理解——加载
- 动态库(共享库)VS静态库
- 动态库链接原理
- 库中地址的理解
- 7. 其他实验
1. 见一见动静态库
我们是否使用了库?答案:肯定的!C语言/C++调用的函数就是C库和C++库。
衡量一个语言的好坏的标准:
①应用场景;②语言生态(语言论坛是否好,学习资料是否多且正确)
1.其实,我们在安装VS的时候,就是要安装对应的头文件和库文件,头文件提供方法说明,库提供方法的实现,这是要结合在一起使用的。
2.头文件是在预加载的时候引入的,而库文件是在在链接的时候使用的,链接的本质就是在链接库!
库都会被安装在系统的特定目录下。/usr/lib文件里。库就是二进制文件
头文件一般在/usr/include/,路径里面
【理解现象】
- 我们在VS2019,下安装开发环境——安装编译器软件,安装要开发的语音配套的库文件和头文件。
- 我们在使用编译器,都会有语法的自动提醒功能,需要先包含头文件的。语法提醒本质:编译器或者编辑器,它会自动的将用户输入的内容,不断的在被包含的头文件中进行搜索,自动提醒功能是依赖头文件的。
- 我们在写代码的时候,我们的环境怎么知道我们的代码中有哪些地方有语法报错,哪些地方定义变量有问题?不要小看编译器,有命令行的模式,还有其他自动化的模式帮我们不断在进行语法检查。
2. 动静态库概念
2.1 为什么要有动静态库
提高开发效率——例如:因为存在库,我们不用再自己实现printf等基础功能函数,大大减少了开发时间,从而提高了开发效率。
学习语言中,存在已经存在多个库(轮子),我们要少造轮子,多用轮子,学习轮子为了更好的用轮子!
2.2 定义
- 前缀都是lib,后缀.a表示静态库,.so表示动态库,才是库的名字
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
3. 写一写——库的设计角度
【步骤】
①编写头文件和源文件
②进行打包在同一个文件中
③将源文件经过预处理,编译,汇编形成二进制文件.o
④打包.o文件成库
打包成静态库
注意:命名规则,前缀lib,后缀.a,中间才是库的名字mymath
打包成动态库
gcc 编译需要加上fPIC选项,形成的.o:与位置无关码
【动态库gcc进行打包】
⑤ 将头文件放在include的文件夹里,将库放到lib文件夹里,进行压缩打包。
⑥将压缩包上传到yum源或者githue等开源上,配套上说明文档,就可以给别人使用了!
4. 用一用——使用者角度
4.1 直接使用头文件和源文件(直接给源代码)
4.2 得到头文件和源文件进过处理后形成的二进制文件.o
得到不到源代码。
——文件太多,不好。打包.o文件->引出打包成库的概念
4.3 得到头文件和静态库
【无法直接编译main.c文件】
出现了链接错误的问题!——找不到函数定义的地方
所以,当我们有了一个库,接下来,要将库引入我们的项目,必须让编译器找到头文件和库文件。
4.4 得到静态库的压缩包
①下载压缩包
②进行解压
此时还不能直接编译——找不到头文件
③找到头文件和库文件
【选项说明】
-I加路径——说明在哪里找头文件
-L加路径——说明在哪里找库文件
-l加库文件名(注意要去掉前后缀)
4.5 将头文件和静态库文件安装到系统路径下
此时编译报错是找不到库文件,但是可以找到头文件
此时要指明链接的库的名字
4.6 得到动态库
此时运行会报错–》操作系统找不到链接的库,因为gcc编译的时候只是告诉了编译器库文件的路径,没有告诉操作系统。
静态库是直接拷贝到可执行程序中,而动态库不会!
此时要对动态库进行配置。
总结第三方库的使用关键
- 需要指定的头文件和库文件
- 如果没有默认安装到系统gcc,g++默认的搜索路径下,用户必须指明对应的选项,告知编译器:a.头文件在哪里(大写I选项);b.库文件在哪里(L选项);c.库文件具体的名字(l选项)
- 将我们下载下来的头文件和库文件,拷贝到默认系统路径下——L在inux下安装库!对于任何软件而言,安装和卸载的本质就是拷贝到系统文件特定的路径下!
- 如果我们安装的库是第三方的(语言,操作系统系统接口)库,我们要正常使用,即便是已经全部安装到了系统中,gcc/g++必须用-l 指明具体库的名称!
5. 动态库的配置与使用
5.1 配置环境变量LD_LIBRARY_PATH(临时方案)
将库的路径添加到环境变量中
5.2 在系统库路径下建立动态库的软链接
5.3 配置文件方案
在目录 /ect/ld.so.conf.d/下,添加.conf 的文件名,在里面写入动态库所在的路径
就可以了!!!
6. 动态库的理解——加载
动态库(共享库)VS静态库
静态链接形成的可执行程序,本身就有静态库中对应方法的实现。
静态链接的优点:形成可执行程序后不受库的影响。
缺点:非常浪费资源(磁盘,可执行程序的体积变大加载占用内存,下载周期变长,占用网络资源)
动态库是共享的,不会浪费资源
动态库链接原理
动态链接本质:将可执行程序中的符号,替换成库中的具体地址。
动态库在程序运行时要执行某个函数的时候,OS会根据搜索路径找到库文件,并加载到内存中,管理程序的进程,会通过页表的映射找到库文件在内存中的位置,在映射到虚拟地址的共享区中,这样就可以执行这个函数了。
共享库,只要通过映射到自己的地址空间上,就可以调用相应的方法。
加载库的时候,不会全部加载到内存中,OS会根据实际情况,加载相应的方法到内存中。
库中地址的理解
在程序编译链接形成可执行程序的时候,内部存在地址。
动态库必定面临一个问题:
不同的进程,运行程度不同,需要使用的第三方库不同,注定了,每一个共享空间的空闲位置是不同的。
所以,动态库中的地址,不能采用绝对编址,要采用偏移量,默认从0开始。
通过偏移量,就可以局部加载动态库到内存了!
7. 其他实验
动静态库都存在的时候,默认是动态链接
加-static就是要求静态链接
没有动态库的时候,会链接静态库。(多个库,有动态库就链接动态库,没有就链接静态库,啥都没有就报错)