【Linux】动静态库 |
您所在的位置:网站首页 › linux怎么查看磁盘和文件关系 › 【Linux】动静态库 |
文章目录
📕 见一见📕 静态库的制作命名方法一方法二方法三
📕 制作动态库📕 对动静态库的理解 —— 加载
📕 见一见
在我们写程序的时候,一直在使用各种语言的标准库,比如我们写 C/C++ 程序的时候,#include< iostream > 使用的就是 C/C++ 的标准库。但是实际上,我们引入的只是头文件,而头文件里面只是有对方法的声明,方法的具体实现,是在库里面的。头和库是有对应关系的,是要组合在一起使用的。 头文件是在预处理阶段引入的,链接的本质就是链接库! 如下,查看指定目录下的文件,这些就是动静态库。其中以 .a 结尾的是静态库,以 .so 结尾的是动态库。(一般而言,云服务器只有动态库,静态库需要自己安装。) 如下是 C++ 的库,我们平时能在C语言程序写 C++ 的代码,就是依赖于它。 这样我们就可以理解一些现象: 我们在 vs2019、vs2022 下安装开发环境,本质上就是安装 编译器、头文件、库文件等等。我们在敲代码的时候,会有自动提示的功能,自动提示的前提是,要包含对应的头文件。自动提醒的本质就是:编译器或者编辑器,根据用户输入的内容,不断地在被包含的头文件中进行搜索。所以自动提醒是依赖头文件的。使用库就是为了提高我们的开发效率!我们要善于用轮子,而不是一味地造轮子!! 📕 静态库的制作 命名 静态库 —— .a动态库 —— .so我们当然可以直接把源代码发给别人,然后让他自己编译。但是一般而言不会这样,无论是从安全性还是便捷性,都不会直接发源代码。所以要将源代码编译成库。 要理解下面的内容,必须要对一个 .c 文件生成 .exe 文件的过程有所了解,可以看一下这篇文章: 你知道 .c 文件是如何变成 .exe 文件的吗? 方法一我们可以把源文件编译生成 .o 文件,发送给对方。如下,一开始只有 myadd.o 和 mysub.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/ 。
然后,只需要告诉编译器,你链接的是哪一个库文件,就可以正常编译了!如下,直接编译不可以,因为这是第三方库(第一方库是语言层面,第二方库是操作系统方面),所以必须要告诉编译器要链接哪个库。
制作动态库,第一步要生成 “与位置无关码”—— 也就是使用 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 |