Linux动静态库的理解
1.回顾
温故知新,少量多次的复习帮助我们更好的掌握知识。我们回顾学过的文件系统,文件系统就是为了管理我们磁盘的文件的,进程管理了被打开的文件,但是我们还需要管理磁盘里未打开的文件,磁盘的基本单位是扇区,一个扇区512字节,IO一次512字节太小了,所以我们一般访问是一下访问8个扇区,4KB大小,我们把8个扇区叫做一个块,我们访问磁盘的基本单位就是块,为了管理磁盘的文件,我们会把磁盘进行分区,就和我们windows里面一块物理盘我们可以给它分ABCD区一样,然后区还是太大,我们把区又分成一个一个组,叫做块组,我们只需要管理好一个组,就管理好了一个区,管理好一个区,就管理好了一块磁盘。一个组里面有super block存储整个分区的INode等信息,inode table里面有一个inode表,还有inodemap和blockmap,我们可以通过位图查看哪个INode和block是否被使用。然后我们的磁盘使用需要格式化,挂载到指定目录下,还为了我们访问效率,避免频繁IO我们会在内存里面缓存目录树,基本单位是dentry,根据我们的算法自动维护这棵树,提高我们的访问效率。这样我们就把我们的文件系统的大致框架走了一遍。下面我们继续来学习新知,库!
2.库
学习库,我们首先要知道,库是什么?
其实,我们很多基本的代码我们在开发中需要频繁使用,比如我们的printf打印的函数,如果我们不使用库,我们就需要去自己实现,这样基本的代码每个程序员都去写一下会浪费我们的资源,所以我们把一些常用的方法就打包成了一个库,后来人使用可以直接调用。
而想让别人使用自己实现好的代码,我们有3种方式,一种给它源代码, 一种是给它.o,一种是给它库。
库的分类有2种,一种是静态库,一种是非静态库。.a是静态库,.so是动态库
静态库的本质就是把库源代码形成的.o文件进行打包交给别人,然后合并自己的代码到可执行程序,这样我们就是静态库的使用方法。静态库一旦形成,因为它把它的代码都合并到可执行程序里去了,相当于把代码拷贝了一份搞里头,所以我们的静态库形成之后就不再依赖我们的静态库了。
我们的代码文件,通过编译器编译成.o文件,叫做可重定位的目标文件,这个时候我们还不能执行,因为还没有进行链接,只是把一个一个.c文件形成了.o文件,还需要对他们进行链接,才可以形成我们的可执行程序。
站在库的使用者角度,我们是怎么进行的呢?
我们的命令一般这样写:
我们进行gcc的时候需要使用-L指定我们的库在哪个路径下,去哪个路径下找这个库,-l后面的是我们的库文件是谁,我们使用一个库需要知道库的路径和库的名称,也就是知道库在哪里,库是谁,由于我们的gcc默认是编译C语言的,所以我们的库会默认去链接我们的C标准库,但是如果我们想要链接其他库,我们需要指明这个库是谁。
当我们不带L的时候我们会去默认路径下查找这个库,库安装就是把库文件拷贝到系统默认路径下/lib64这个指定路径下。
下面我们写一个库来和我们的程序进行链接加深印象,我们进行静态链接:
我们写了一个add的.c和add.h我们需要先把.c文件编译成.o文件,再把.o文件打包成静态库,然后再使用gcc对我们的程序和我们打包好的库进行链接。
我们知道库=库文件+头文件,我们上面介绍了我们的库在哪里,哪个库的问题,那么我们的头文件呢?我们要使用我们的大i指定我们的头文件搜索路径。
这里我们需要知道我们得库在哪的问题会去默认路径下搜索的,头文件在哪的问题也会去默认的路径下搜索,如果我们不想进行指定,我们只需要安装在默认路径下即可。
但是我们的哪个库需要我们需要自己指定。
那么为什么我上面演示的那个库文件的链接,我没有包含头文件的寻找位置,它也链接成功了?
上面我们讲述的是静态库的链接方法,下面我们对动态库的链接进行介绍。
图中是我们动态库的基本思路:
和静态库一样,只不过区别是我们需要先创建一个位置无关码
然后把库形成.o,可重定位的二进制文件
然后把我们的.o文件进行打包
然后形成我们的可执行的文件
但是我们运行的时候会发现我们的可执行文件会报错,无法找到我们的库,为什么呢?我们不是已经告诉了-l -L指定了是哪个路径下去找,并且告诉是哪个库了吗?为什么还是不行,答案是我们那个-L -l都是我们在编译器编译时做的工作,但是我们编译完毕之后,和我们的编译器就没有关系了,静态库能找到是因为编译器会把我们的静态库打包进我们的二进制文件,但是我们的动态库无法找到是因为我们编译好之后去默认路径下去查找找不到哦!所以我们的解决方法就是让它在默认路径下找到就可以了。
我们实践中,一个是在lib/64下建立软连接,还有就是把我们的库直接拷贝进我们的lib/64里就好了。
总而言之,我们的库分为动态库和静态库,库=库文件+头文件。
我们编译的时候,如果我们使用库的内容,我们需要找到头文件和库文件,头文件的查找,如果我们是《》我们会去默认路径下查找,如果是“”我们会去当前目录下优先查找,而我们的库文件查找,无非就是库文件在哪?并且指定是哪个库文件就可以了,首先我们如果不指定路径我们去lib/64的默认路径下去查找,-L可以指定我们的查找路径,而哪个库文件我们是必须指定的,只不过我们的gcc是C,默认会加入我们的C标准库!
然后我们的库文件写好之后我们需要对他们进行编译成.o文件,对他们进行打包。打包我们分为懂动态库方式打包,静态库的方式打包。
但是我们都需要先把我们的文件编译成.o文件才能进行打包哦!
.o文件打包成静态库和打包成动态库有不同的打包工具。
打包好了之后我们编译的时候就可以把它和我们的.C文件一起编译就可以使用了!!!
动态库打包好之后需要到搞到我们的lib/64里哦,不然编译器找不到,静态库不需要找,要找的话它也找不到,因为静态库直接把它的文件和我们的.c文件搞一块了。
而且动态库打包之前还需要生成我们的位置无关码。