静动态库
- 一.静态库
- 1.设计静态库
- 2.生成静态库
- 3.发布静态库
- 4.使用静态库
- 二.动态库
- 1.设计动态库
- 2.生成和发布动态库
- 3.使用
- 三.进程地址空间
- 1.程序在加载前的地址
- 2.程序在加载后的地址
- 3.动态库的地址
一.静态库
程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
静态库链接格式:libxxx.a(前缀是lib,后缀是.a)
1.设计静态库
用mymath.h声明,mymath.c作为实现
2.生成静态库
第一行:形成一个库,叫做libmymath.a
第二行:依赖的文件mymath.o,并且把所有依赖的.o文件打包成一个.a文件(ar是生成静态库的指令,rc是releace和create,连起来就是把后面的文件打包到前面的文件里)
第三行:把所有依赖的源文件变成.o文件 最后进行清理**
这样库就形成了,总结一下就是把所需要的.o文件全部用ar打包成一个.a文件就行了。
3.发布静态库
创建include和mymathlib两个文件在lib里,在将所有的.h文件拷贝到include里,将所有.a文件拷贝到mymathlib里。
4.使用静态库
第一种使用方法
这里直接编译是会报错的,原因很简单。在编译时会进行头文件展开,那么第一件事情就是找到对应的头文件,而它会在默认的路径下查找,但默认的路径里很明显不包括我们自己写的库,所以必须指定路径。
1.-I 选项代表到指定目录下查找头文件
2.-L 选项代表到指定目录下查找库文件
3.-l 选项代表指定的库(库的名字去掉前缀和后缀)
第二种方法
gcc会默认在默认目录里搜索,那么我们可以自己把头文件和库拷贝到对应默认目录里(或者添加软链接)。
但是gcc只认c库里的文件,所以要使用第三方库依然要加-l选项。
二.动态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
动态库:前缀是lib,后缀是.so
1.设计动态库
接下来就用这两个源文件打包形成动态库。
2.生成和发布动态库
动态库的生成与静态库差别不大,这里将动静态库连起来使用。
shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
从上面看到一个.a库和一个.so库合并成了一个lib库。
3.使用
三.进程地址空间
1.程序在加载前的地址
当程序在磁盘里时有地址的概念吗?答案是有的,程序在加载到内存之前也是要有地址的概念。在平坦模式下,编址从0~4GB.
其实这些地址也被称为逻辑地址(虚拟地址),在程序未被加载前就已经存在地址了。
2.程序在加载后的地址
程序是可以在任意位置加入到内存,所以程序加载后必须有一个物理地址,由于程序在加载前就有了地址,所以程序在加载到物理内存里后实际上有两套地址。
那么cpu是如何找到程序的呢?
系统里有一个EIP寄存器,会保存该程序的入口地址,所以CPU只需要得到这个入口地址,就可以根据程序本身的逻辑地址正常执行代码了。
3.动态库的地址
动态库加载到物理内存后,毫无疑问需要通过页表映射到虚拟内存的共享区,那么具体映射到共享区的哪个位置呢?
1.由于一个动态库有不确定性,也就是说操作系统并不确定这个库是否会使用,使用的顺序,所以就不能给库一个固定的位置。换句话说该库应当是可以加载到共享区的任意位置的。
2.由上可以得出,库本身在编址并不使用绝对地址,而使用偏移量。
3.所以只需要提供该库的起始地址,通过偏移量就能执行所有代码。
4.在生成动态库时的fPIC(产生位置无关码)指令,就是告诉编译器使用偏移量进行编址。