动静态库的原理和实现
1. 磁盘

磁盘的描述性结构

盘面、柱面、扇区就能定位到我想找的文件。但是对于操作系统来说,他不可能还要关心这里问题,所以把物理的地址转化为了对于逻辑数组的管理。

2. 文件系统
可以理解为每一个盘面就是一个分区,但是这个分区还是太大了,所以还需要分成很多的块组(Block group),那么管理好一个块组类比于其他的,就能把所有的块组都管理好,也就可以把这个分区管理好了。

这个为磁盘文件系统图
- Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。
- 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。SuperBlock的信息被破坏,可以说整个文件系统结构就被破坏了
- GDT(Group Descriptorable):块组描述符,描述块组属性信息(这一个块的具体信息)
- 块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
- inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
- inode Table节点表:存放文件属性如文件大小,所有者,最近修改时间等(一个文件只有一个inode)
- Date blocks数据区:存放文件内容(一个文件可能会有多个blocks)
3. inode
存放文件的属性
inode中必须包含Date blocks对应的映射关系,inode里面有一个数组,存放着和这个文件相关的blocks,拿着这个数组里存放的下标,就可以找到这个文件所有的blcoks。

目录也是文件=inode+数据块(文件名:inode id)
4. 软硬链接
硬链接
ln new.txt h_link 就会生成一个h_link的新文件,会发现这个文件和你的new.txt文件的inode是一样的。 所以硬链接不是一个独立的文件

那么硬链接到底是什么呢?
文件名和inode对应的映射关系的个数。

此时不管你打开h_link还是new.txt文件,他们操作的都是通过同一个inode找到的文件。
软连接
ln -s log.txt link 生成一个link -> log.txt 的文件,那么和原本的log.txt有什么区别呢?

会发现生成的软连接有一个inode和原本的log.tet文件的inode是不一样的。所以软连接是一个独立的文件
如果项目比较深的话,可以把可执行程序直接的放在bin目录下面,那么你就可以不用在一步步深入目录去寻找了,而是直接的./start.link就可以运行。

5. 认识并制作动静态库

5.1 静态库
对于静态库的编写只需要在Makefile中的gcc -o $@ $^ -static加static就好了,就会生成静态库文件,对比于静态库和动态库生成的文件,静态库生成的文件体积非常的大(占用硬盘的资源),当你的程序中有多条printf语句的时候,那么就会出现多份从C库中拷贝过来的printf的实现方法(占用内存的资源)

静态库的原理:直接将对应的代码拷贝进bin,体积比较大,bin的可移植性强

5.1.1 静态库的实现
首先要明白,我自己制作的库目的是为了去给别人直接的使用,那么所交给别人的库就需要包含
- 一批头文件:有什么方法可以使用,接口参数是什么意思。
- 一个或多个库文件:具体的实现,供我们动静态链接
静态库粗暴一些就可以理解为:把我的代码生成的.o文件都进行打包,改名为.a

①把所有的.c文件都进行gcc -c xxxxxx.c 会生成同名的.o文件

②把所有的.o文件都进行打包,会生成一个.a文件 ar -rc libmymath.a myadd.o mysub.o mymul.o mydiv.o
ar是gnu归档工具,其中rc表示(replace and create)

③我要把我打包好的静态库和头文件给别人使用,创建一个mylib的文件,在mylib里面放着一个include文件,用来存储我的所有的头文件,lib文件用来存储我所打包好的静态库


5.1.2 静态库的使用
我把我的库打包好给别人使用,但是会发现,即使mylib在当前目录下面可是依旧会报错,说明默认是找不到的。
#include<stdio.h>
#include<myadd.h>
#include<mysub.h>
int main()
{
int x = 10;
int y = 5;
printf("add : %d\n",MyAdd(x,y));
printf("sub : %d\n",MySub(x,y));
return 0;
}

- -I :指针自定义头文件路径
- -L:指定自定义库路径
- -l:指定库名


其实我们还可以把对应的头文件和库文件放在对应的系统里面,在Makefile中要默认还是带上-l mymath这个选项就行,但是并不建议这样去使用,因为你这样做会污染原本的头文件池和库文件池。
5.2 动态库
并不把库中的代码给我们拷贝过来,所以生成的可执行程序的体积相对较小,但是非常的依赖C库,且在运行的时候才加载,可以只有一份
动态库的原理:

5.2.1 动态库的实现
- shared: 表示生成共享库格式
- fPIC:产生位置无关码(position independent code)
- 库名规则:libxxx.so


发布的版本:

make output,就会看见一个mylib的文件

5.2.2 动态库的使用
此时使用一个我所创建的动态库。


然后make,你就会发现可以生成可执行程序,但是运行不了。

原因是找不到库,那我已经指定了我的库搜索路径了呀,为什么还找不到呢?是因为编译器可以找到这个库的位置,但是操作系统找不到,所以需要改环境变量,LD_LIBRARY_PATH ldd 文件用来查看文件所依赖的库
export LD_LIBRARY_PATH=/home/wzy/lesson_19/new/mylib/lib改完之后,就可以运行了

本文介绍了磁盘、文件系统、inode及链接的基础概念,并详细讲解了动静态库的原理与实现方式,包括静态库的实现与使用,以及动态库的实现与使用。
4606

被折叠的 条评论
为什么被折叠?



