Linux基础内容(18)—— 动静态库

 Linux基础内容(17)—— 软硬链接_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/129916616?spm=1001.2014.3001.5501

目录

1.引例

2.解决引例的问题

3.静态链接 

1.打包过程

2.方案一

3.方法二

4.动态链接

1.打包过程

2.方法一

3. 方法二

4.方法三

5.方法四

5.动静态库的加载

1.静态库的加载

2.动态库的加载

6.对比

动态库

静态库


1.引例

在实际中,我们可能不想提供给别人源代码的内容,但是别人又需要用到我们写的函数,那么一般的操作就是把源文件形成的.o文件给别人,并且把头文件一并给别人,这样别人可以使用该文件的内容,但是不知道源代码是如何实现的。我们称.o文件为可重定位二进制文件。

之后调用文件,只需要在当前路径下有可重定位文件和头文件,并且执行文件时包头文件。这样文件就被调用了,不过目前还有一些值得思考的问题:

1.为什么C语言的函数就包头文件即可运行了?

2.有什么办法可以让我们的文件也像C库的调用一样?

2.解决引例的问题

1.C语言能运行是因为C库的,那么在变成可执行文件之前的链接过程就是将头文件的内容和C库的文件链接。

2.我们如果想想C库的执行文件一样,那么一定要学会动静态链接的执行操作。在此之前还得解释一下怎么链接的。

3.一方将可重定位二进制文件和头文件打包压缩,随即传送给另一方;或者上传社区,另一方在社区得到社区。随后解压缩,包头文件,链接可重定位二进制文件,或者用动静态链接

4.文件包头文件,链接可重定位二进制文件只能在当前路径或者系统文件中找到,如果没有说明需要指定位置

5.链接文件的前缀是lib,.a是静态库,.so动态库

3.静态链接 

1.打包过程

Linux基础内容(18)—— 动静态库_第1张图片

1.指定生成静态库文件 

2.add.c和sub.c执行加减法,而后打包了其生成的.o文件和.h文件到mylib中

3.这里的打包是一种归档指令 ar -rc libmymath.a my_add.o my_sub.o

4.mylib打包文件送到了main.c路径下

5.main.c执行另一个人发送的过来的打包文件

6.当然现在执行不了这个文件,其原因就是虽然有了链接的文件,但是系统默认链接当前路径的或者系统的地址的文件,如图

 上面的预设情况,系统找不到文件,那静态链接如何解决呢?

2.方案一

Linux基础内容(18)—— 动静态库_第2张图片

Linux基础内容(18)—— 动静态库_第3张图片

总结一下这种方案:

1.要生成可执行文件需要知道所有的位置和文件名

2.-I表示找到头文件 -L表示可重定义二进制文件的位置 -l表示链接文件的名字,去掉前缀和后缀

Linux基础内容(18)—— 动静态库_第4张图片

 查看链接,发现都是.so的,是否说明这不是静态链接呢?

答案是否定的,系统默认是动态链接的;形成一个可执行文件不仅仅调用一个库,那么只要有链接静态库就是静态链接。因为我们gcc找不到.a对应的.so文件,那么默认动态链接也没有用,因为根本没有,所以是静态库。

3.方法二

前面一种是自己去找,现在说明如何装到系统文件中,这样不需要手动链接。

Linux基础内容(18)—— 动静态库_第5张图片

将头文件和链接文件放到系统中,这种操作其实是安装。

Linux基础内容(18)—— 动静态库_第6张图片

 此时也还是不能生成可执行文件,不过的错误是没有告诉gcc用哪个文件

Linux基础内容(18)—— 动静态库_第7张图片

不过这个方法不太推荐,我们临时写的文件没有经过测试。 

4.动态链接

1.打包过程

Linux基础内容(18)—— 动静态库_第8张图片

形成.o需要:gcc -c -fPIC 文件名    (方便后续我会改成my_add.o文件)

-fPIC:形成位置无关码 

打包动态库,gcc自己就提供,不需要我们用归档指令 

Linux基础内容(18)—— 动静态库_第9张图片

最后将文件打包,发送到另一方去。

Linux基础内容(18)—— 动静态库_第10张图片

2.方法一

Linux基础内容(18)—— 动静态库_第11张图片

该方法与静态链接的方法一致,不过此时不能运行 

这条语句说明加载动态库时,不能打开共享对象,因为没有该文件。

Linux基础内容(18)—— 动静态库_第12张图片

那么查看动态链接的文件,发现确实not found 。

这是为什么?

我们指令只告诉gcc库的位置,程序生成后与gcc无关了;但是当程序执行操作系统也需要知道链接的位置,操作系统找不到,所以错误。

怎么处理呢?

1.操作系统除了在系统文件找动态库,会在环境变量里找动态库

$LD_LIBRARY_PATH:就是环境变量的动态库

expert LD_LIBRARY_PATH=$LD_LIBRARY_PATH:指定的动态链接文件位置

Linux基础内容(18)—— 动静态库_第13张图片

(这样的环境变量是临时的,它不会让我们在下一次还可以执行)

上面是临时的方法,下面介绍一劳永逸的方法。

3. 方法二

拷贝到系统文件中即可,与静态链接方法一致,由于步骤一致,不重复说明。

4.方法三

/etc/ld.so.conf.d/,该文件中有配置文件,即为动态库搜索时,我们可以自定位置,使得操作系统能够找到链接文件。

Linux基础内容(18)—— 动静态库_第14张图片

我们只需要把需要链接的文件路径复制到该文件中就可以了。

Linux基础内容(18)—— 动静态库_第15张图片

Linux基础内容(18)—— 动静态库_第16张图片

最后更新缓存 sudo ldconfig ,这样就可以了。

5.方法四

当前路径永久生效

软链接需要链接的文件,随后就可以在本地路径下生成执行文件。 

随意路径永久生效

将软链接文件建立到系统路径(/lib64)中即可

5.动静态库的加载

1.静态库的加载

1.静态库的加载其实就是拷贝链接文件里的内容到源文件中,形成可执行文件

2.在没有加载时,静态链接文件已经将其内容拷贝到可执行程序的虚拟地址空间中的代码段

3.程序运行访问链接的代码就是在页表中找到代码段对应的函数进行执行,与用户写的函数一样

2.动态库的加载

1.为了找到链接的文件,动态库会把指定函数的地址加载到可执行程序中。

2.地址+偏移量表示一个动态库的函数,当我们要加载时,系统找到对应库的文件和文件的偏移,随后加载到内存,内存的内容映射到共享区。在共享区中,我们就可以调用这个函数了

3.调用函数,程序会在共享区找函数对应的在库里的偏移量,随后到库中找到函数,这样我们就可以执行链接的函数了

6.对比

动态库

1.节省空间

2.动态库函数修改后,不需要重新编译

3.加载速度慢

4.开发模式好,因为经过测试的代码才一般在动态库中

5.共享

静态库

1.加载速度快

2.耗费空间多

3.修改静态库后,需要重新编译可执行文件

你可能感兴趣的:(linux,c语言,服务器,centos)