【Linux】动静态库

您所在的位置:网站首页 linux怎么查看磁盘和文件关系 【Linux】动静态库

【Linux】动静态库

#【Linux】动静态库| 来源: 网络整理| 查看: 265

文章目录 📕 见一见📕 静态库的制作命名方法一方法二方法三 📕 制作动态库📕 对动静态库的理解 —— 加载

📕 见一见

在我们写程序的时候,一直在使用各种语言的标准库,比如我们写 C/C++ 程序的时候,#include< iostream > 使用的就是 C/C++ 的标准库。但是实际上,我们引入的只是头文件,而头文件里面只是有对方法的声明,方法的具体实现,是在库里面的。头和库是有对应关系的,是要组合在一起使用的。

头文件是在预处理阶段引入的,链接的本质就是链接库!

如下,查看指定目录下的文件,这些就是动静态库。其中以 .a 结尾的是静态库,以 .so 结尾的是动态库。(一般而言,云服务器只有动态库,静态库需要自己安装。) 请添加图片描述

如下是 C++ 的库,我们平时能在C语言程序写 C++ 的代码,就是依赖于它。 请添加图片描述

这样我们就可以理解一些现象:

我们在 vs2019、vs2022 下安装开发环境,本质上就是安装 编译器、头文件、库文件等等。我们在敲代码的时候,会有自动提示的功能,自动提示的前提是,要包含对应的头文件。自动提醒的本质就是:编译器或者编辑器,根据用户输入的内容,不断地在被包含的头文件中进行搜索。所以自动提醒是依赖头文件的。

使用库就是为了提高我们的开发效率!我们要善于用轮子,而不是一味地造轮子!!

📕 静态库的制作 命名 静态库 —— .a动态库 —— .so

我们当然可以直接把源代码发给别人,然后让他自己编译。但是一般而言不会这样,无论是从安全性还是便捷性,都不会直接发源代码。所以要将源代码编译成库。

要理解下面的内容,必须要对一个 .c 文件生成 .exe 文件的过程有所了解,可以看一下这篇文章: 你知道 .c 文件是如何变成 .exe 文件的吗?

方法一

我们可以把源文件编译生成 .o 文件,发送给对方。如下,一开始只有 myadd.o 和 mysub.o ,这是二进制文件,并不是源代码。然后一起编译,生成目标文件。

请添加图片描述 但是这种方法未免有点…不太优雅。当 .o 文件多了起来,就不方便了,所以可以将这写 .o 文件打个包。

方法二

如下,使用 ar -rc 指令将所有的 .o 文件打包,生成的 libmymath.a 就是静态库。

请添加图片描述

当我们有了一个库,要将库引入项目,必须要让编译器找到头文件和库文件。如下,直接 gcc 会报错,这是因为,我们自己生成的 libmymath.a 是一个第三方文件,gcc 并不能理解它。但是 gcc 能理解 C/C++ 的库,这是因为 gcc 本来就是为了它们设计的!

请添加图片描述

所以,我们需要告诉编译器,要使用 libmymath.a 这个库。如下,可以使用 -l ,告诉编译器用哪个库,但是,直接 -l 后面跟的要是库的名字,需要去掉前缀后缀,所以 libmymath.a 这个库的名字实际上是 mymath 。 同时,也需要指明这个库的路径,用 -L 标识(这里演示的时候,它默认在当前路径下寻找了)。

请添加图片描述

如下,我们将头文件放在 inlcude 目录下,将库文件放在 lib 目录下,然后编译 main.c ,一开始的大写的 i 标识的是头文件路径。这里就必须要指明 头文件路径、库文件路径、库文件 才可以成功编译。 这就相当于是独立的开发出了一个库。 在这里插入图片描述

所以,如果使用第三方库,并且没有默认安装到系统 gcc、g++ 的默认搜索路径下,用户必须指明对应的选项,告诉编译器——头文件在哪里、库文件在哪里、具体用哪个库。

方法三

可是,实际上我们不会像上面这么用。

首先,我们将头文件拷贝到系统默认搜索头文件的目录下,即 /usr/include/ 。

在这里插入图片描述 其次,我们将库文件拷贝到系统默认搜索的库文件目录下,即 /lib64/ 。

在这里插入图片描述

然后,只需要告诉编译器,你链接的是哪一个库文件,就可以正常编译了!如下,直接编译不可以,因为这是第三方库(第一方库是语言层面,第二方库是操作系统方面),所以必须要告诉编译器要链接哪个库。

在这里插入图片描述 所以,我们将 头文件 和 库文件 下载到默认路径下,就是在 Linux 下安装库!!卸载反之。

📕 制作动态库

制作动态库,第一步要生成 “与位置无关码”—— 也就是使用 gcc -fPIC 指令生成 .o 文件。(fPIC:产生位置无关码(position independent code))

在这里插入图片描述

其次,使用 gcc 的 继续打包生成 .o 文件,使用 -shared 选项,生成动态库。(shared: 表示生成共享库格式) 在这里插入图片描述

然后,将动态库放入 lib 目录下,用之前的方式生成可执行文件。如下图,执行时发现找不到 libmymath.so 这个动态库文件。 这是因为, .so 文件并没有在系统的默认搜索路径下,所以 OS 依旧找不到!! 可是为什么静态库可以找到?这是因为,静态库链接的时候,是将二进制代码全部拷贝到可执行程序中,而动态库是需要的时候再去 .so 文件里找!

请添加图片描述

如下,通过使用 ldd 指令,可以看出是动态库无法找到。

在这里插入图片描述

这里有三种解决方案,这三种解决方案都是让程序运行的时候,操作系统可以找到动态库的。

环境变量

这里用到环境变量 LD_LIBRARY_PATH

将动态库的路径添加到环境变量里面,这样就可以了。但是,这是一种临时方案,当我们退出Xshell 之后,就会失效。 在这里插入图片描述

软链接

第二种方法,就是在系统默认路径下添加软链接,让软连接指向动态库文件,由于软链接是在磁盘上的,永久存在,只要不删除就可以一直用。

在这里插入图片描述

配置文件

第三种是修改配置文件,如下图,在 /etc/ld.so.conf.d/ 目录下,有各个配置文件,文件里的内容就是动态库的路径,所以,我们要在这里把自己的动态库路径添加进去。

第一步,在该目录下创建一个 dynamic.conf 文件,然后将自己制作的动态库路径放进去。 在这里插入图片描述

光是做完上面的步骤还不够,如下图,依然找不到动态库,并且无法运行可执行程序。

这是因为 我们虽然添加了新的配置文件,但是,配置文件还没有生效。所以要用 ldconfig 指令让配置文件起作用(要用到 sudo 权限),然后用 ldd 指令查看文件,找到了动态库,并且可执行程序也能跑起来了! 在这里插入图片描述

📕 对动静态库的理解 —— 加载

对于静态库而言,它是直接把整个库里面的内容,放到可执行程序里面,这样子会造成可执行程序占用的内存变得很大。

但是动态库不会这么做,动态库会加载一份到内存,然后可执行程序要调用的时候,直接将动态库的地址,通过页表映射到可执行程序的共享区。要调用库里面的内容时,代码段的内容会找到共享区里 动态库的地址,继而找到动态库去调用,这样子,代码执行库中的方法,就依然是在自己的进程地址空间之内进行跳转。

对于动态库而言,其内部地址并不是采用绝对地址的方式,因为动态库每一次加载到内存中的位置并不是一样的,所以动态库不能采用绝对编址。那么就只能采用相对寻址,动态库内部的地址,相对于该库的起始地址偏移量,这样子只需要知道动态库加载到内存的起始位置即可。有了动态库在内存中的起始地址,要找库里的方法,只需要知道方法和起始地址的偏移量。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3