Linux——动静态库

文章目录

  • 静态库
    • 制作
    • 静态库使用
  • 动态库
    • 制作
    • 使用
  • 动态库的加载

静态库

制作

首先我们制作一个简易的计算文件,分多个.c和.h文件
Linux——动静态库_第1张图片

库中是没有main函数的,我们也不能把main函数写入我们的库中。

Linux——动静态库_第2张图片
Linux——动静态库_第3张图片

再来一个测试文件
Linux——动静态库_第4张图片

对这些文件进行编译
gcc -o Test Add.c Sub.c Mul.c Div.c TestMain.c
Linux——动静态库_第5张图片

头文件的查找是在当前目录下或者在系统的指定目录下查找的

运行可执行程序
Linux——动静态库_第6张图片

但是如果我们像上面那样都进行编译形成可执行程序的话,那么每一个源文件都需要进行预处理、编译、汇编、链接的过程,就会显的很麻烦。但是如果我们把这些源文件进行编译汇编形成.o文件(可重定位目标文件)

对Makefile进行编辑

Test:Add.o Sub.o Mul.o Div.o TestMain.o
     gcc -o $@ $^
 
%.o:%.c
     gcc -c $<
 
.PHONY:clean
clean:
    rm -f *.o Test      

Linux——动静态库_第7张图片
我们make一下就形成了对应同文件名的.o文件和可执行程序Test
Linux——动静态库_第8张图片

也就是我们将TestMain.c形成.o文件后,将其和.o和.c文件链接后形成了可执行程序a.out

如果我们将所有的.o文件打一个包,将他交给使用者,使用者只需自己写出.c并且将其编为.o,然后和打包好的.o进行链接就可以了。

Linux——动静态库_第9张图片
如果.o文件过少,我们使用上述gcc处理还可以,但如果数量上去的话就有些麻烦,所以我们需要制作一个库文件、
ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)
我们先修改一下Makefile
Linux——动静态库_第10张图片
之后就形成了一个libmymath.a的静态库
Linux——动静态库_第11张图片
静态库,本质就是将库中的源代码直接翻译成为.o目标二进制文件,然后打包

静态库使用

朴素做法
首先我们用上面的一段测试程序
Linux——动静态库_第12张图片
然后我们想使用libmymath.a那个库
但是当前这个目录下没有库,编译都编不过(头文件报错)
Linux——动静态库_第13张图片
Linux——动静态库_第14张图片
对TestMain.c进行编译
在这里插入图片描述
我们都把所有东西给他了并且提供了这个库,但是还报错这是因为
gcc默认情况下是不认识第三方库的,虽然提供了,它能看见,但是不认识。


我们可以使用下面的指令
gcc TestMain.c -lmymath -L.
Linux——动静态库_第15张图片
-l指定库名为mymath
-L指定库路径为当前目录下
Linux——动静态库_第16张图片

我们平时所用的C标准库并没有用到 -l , -L选项,是因为gcc认识c标准库的,我们所写的libmymath.a叫做第三方库

查看一下a.out的依赖库
在这里插入图片描述
并没有依赖我们的mymath
原因是因为这些依赖的库都只是动态库,而静态库已经把自己的代码拷贝到可执行程序里面了,没办法查。可执行程序既依赖了动态库,又依赖了静态库可执行程序依赖的库有动态链接的优先动态链接,如果又特定的库只提供静态库那也没办法,会把静态库拷贝到可执行程序,也就是说一个可执行程序依赖的库可以是动静态库混杂的现象。
gcc默认动态链接的,但个别库,如果你只提供a,gcc也没有办法,只能局部性的把你指定的.a,进行静态链接,其他库正常动态链接,如果-static,就必须要,a


用户使用我们的库,总不能发一堆.h和.a我们应该静态库归静态库,头文件归头文件进行包装,我们再次修改Makefile
Linux——动静态库_第17张图片
make形成对应的.a静态库文件,make output发布,形成了一个mymath_lib的库
Linux——动静态库_第18张图片

Linux——动静态库_第19张图片
将这个库打包
Linux——动静态库_第20张图片
用户下载这个压缩包,解压之后我们就得到了一个库
Linux——动静态库_第21张图片
如何使用???
首先我们需要知道
头文件,默认在/usr/include目录
库文件,默认在/lib64目录

  1. 我们直接将下载下来的头文件和库文件放在上面所说的目录下;
  2. 利用gcc的选项来让gcc去指定目录下去找

Linux——动静态库_第22张图片
在这里插入图片描述

如果我们把库安装到系统里了,我们只需写-l(指明链接的库名称);

动态库

制作

动态库的生成

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 库名规则:libxxx.so

动态库的生成和静态库是一样的,也是将源文件生成的.o文件打包形成对应的动态库
gcc编译的时候要对源文件编译时使用的选项不再是ar -rc 了,而是要-fPIC选项(产生位置无关码)。
要将其打包成一个动态库,需要使用-shared,也就是让它生成共享库。


gcc不仅可以形成可执行程序,还可以形成动态库
首先,修改Makefile里的文件
Linux——动静态库_第23张图片

make一下,就形成了一个.so的动态库

Linux——动静态库_第24张图片
make output发布
Linux——动静态库_第25张图片
Linux——动静态库_第26张图片
在这里插入图片描述
Linux——动静态库_第27张图片

报错原因是:加载共享库(libmymath.so)的时候,不能打开这个文件
我们使用编译器的时候,我们所用的-I -lxxx -L选项就告诉了编译器应该去哪里找这些头文件和库文件
前面使用静态库的时候,它会找到这些文件并且拷贝到可执行程序中,运行的时候就不用再找一遍了;

现在使用动态库的时候,编译时将库文件和头文件搜索路径都告诉了编译器,但当我们编译完成后,该./a.out运行时程序就与编译器无关了,而是和系统有关可执行程序运行的时候去/lib64/lib下去找。即使提供了动态库,但是系统并不会去其他目录下查找。

使用

我们可以用以下方式来链接动态库
方法一:直接安装到系统中
两个默认的路径:/lib64和/usr/include中
Linux——动静态库_第28张图片

方法二:使用软链接查找动态库
Linux——动静态库_第29张图片

方法三:使用环境变量
Linux——动静态库_第30张图片

方法四:更改配置文件
在这里插入图片描述

Linux——动静态库_第31张图片


如果同一组库提供动静态库两种库,gcc编译器默认优先使用动态库

动态库的加载

gcc -fPIC xxx.c
上面的fPIC,什么叫做位置无关码?
首先我们需要知道在Linux下,可执行程序是ELF格式的,也就是说通过将源代码编译会形成ELF格式的可执行程序

  1. 可执行程序要加载到内存的时候需要链接对应的动态库,不仅可执行程序要加载到内存,而且需要链接的库也要加载到内存中。
  2. Q:程序没有被加载到内存,程序有地址吗???
    A:有!
    Q:函数名等编译成为二进制对应的函数名,变量名还有吗???
    A:没有! 编译的时候,对代码的编址,基本遵守地址空间那一套,虚拟地址空间不仅仅是操作系统的概念。编译器编译的时候,也要按照这样的规则编译可执行程序,这样才能在加载的时候,进行从磁盘文件到文件内存,再进行映射

我们的可执行程序在没有加载到内存的时候,就已经有了虚拟地址对应的概念了,比如说代码区中的A函数去调用B函数时,call后面跟的地址就是A函数的虚拟地址 ,其实我们一般把这样的地址叫做逻辑地址,逻辑地址其实就是基地址+偏移量这样的概念,也就是把0-FFFFFFF理解为:0(基地址)+[0,FFFFFFF](偏移量)

  1. 绝对编址,相对编址
    Linux——动静态库_第32张图片
    当跑道的起始地址改变的时候,我的位置20也要发生改变,这是通过采用绝对编址要发生的变化;但采用相对编址,当跑道起始地址发生变化时,树的地址也要发生变化,但是我对树的相对地址还是在树的左边30米,这个相对编址就是偏移量△x;因为我们的可执行程序加载到内存的时候并不会加载到一个固定的位置,每次进来加载地址都会发生变,采用偏移量的方式来编址,除了起始地址变了,其他的偏移量都没有发生变化,这就是所谓的fPIC(位置无关码)。
  2. 库被加载后,要被映射到指定使用了该库的进程的地址空间中的共享区部分。
    但是并不会映射到共享区的任意位置;一旦加载成功,位置就是确定的;
    我们也做不到让库在共享区中任意位置加载到位置
    Linux——动静态库_第33张图片

Linux——动静态库_第34张图片
在学校的时候,老师只知道计科2201班学生的学号,但并不知道他的宿舍,但是计科2201班的班长知道这个学号对应的宿舍,因为班长有一张表,映射这学号<—>宿舍;
好比,老师要找5号学生,班长一看表,嗯,5#123宿舍,也就是5号<—>5#123宿舍 ;
上面的,老师<—>指令寄存器、那张表<—>页表、学号<—>虚拟地址、宿舍<—>物理地址

你可能感兴趣的:(Linux,linux,服务器,笔记)