Linux之静态库和动态库

目录

一、前言

二、对于库的理解

三、静态库

四、动态库

五、动静态库的加载


一、前言

在之前,我们讲了静态库和动态库,详情请跳转:静态库和动态库

下面我们将从工程师的角度,去了解静态库和动态库的形成过程,以及实现它们的制作。并且了解如何将自己的库交给别人,让别人也可以使用。

二、对于库的理解

Linux的库一般分为动态库和静态库:

静态库:库文件以 .a 为后缀,程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。

动态库:库文件以 .so 为后缀,程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

gcc 在编译时默认使用动态链接,链接动态库,而如果想生成静态链接,我们需要在末尾带上 -static。

而我们知道,程序编译链接的最后,其实就是将各种 .o 可重定位目标二进制文件包括 main 函数的 .o文件,与所包含的 .h 文件全部链接起来,形成可执行程序。所以,这是不是就意味着,用户真正需要的库文件其实是 .o 文件,设计者可以不用将源文件提供给用户,而直接将.o和.h文件提供给用户,以供用户链接。这样不仅方便,而且能够保护源码。这样可以吗?

如下图,在该目录下,我们只有.h和.o文件,没有这些文件的源码。那么能编译成功吗?

编译结果如下:

我们发现,编译出的可执行程序能够运行。 

但是如果存在很多.c文件呢?难道我们要把几千个.c文件全部编译成.o在加上头文件全部一个一个提供吗?那样太过于麻烦,为了让用户更好的使用库,我们就有把所有的.o文件打成一个包,给对方提供一个库文件。

所以,库中包含了多个.o文件。

三、静态库

我们可以使用 ar 命令(把所有的.o打包起来),来制作一个静态库。比如:我们要打包二中所讲到的.o文件:

ar -rc libexe.a myadd.o myprintf.o

当然,我们也可以写一个Makefile来快速制作一个库。

output:而我们要交付库,实际上要把库文件 .a 以及匹配的头文件都交付给用户,而output就相当于一个发布的过程。

好了,那么静态库我已经制作好了,且已经发布了,那么我们来使用一下自己制作的库。首先,我们将库拷贝到 mylib 目录下去使用。

但是,当我们编译时,却出错了:

gcc在编译时,找不到头文件!!! 

解决方法:编译器搜索头文件时默认在当前目录下搜索,在系统默认指定路径下搜索。虽然此时的mylib在当前路径下,但是头文件太深了,编译器找不到头文件,所以我们需要给gcc指定路径。如下:使用选项 -I 告诉编译器头文件所在路径。

问题又来了,gcc找不到库函数的实现。我们在形成可执行程序的时候,库文件要使用的话也要知道库所在的路径在哪里,系统的默认路径是/lib64,而这是我们自己制作的库,不在里面。所以我们要带上 -L。告诉库的路径在哪里。因为该路径下可能有多个库,所以我们还要使用 -l 选项,加上库名字去掉前缀和后缀 .a。

 如上图,我们编译并且运行成功了。

总结:

-I:指明头文件的搜索路径

-L:指明库文件的搜索路径

-l:指明要链接哪个库,带上库的名称(去掉前缀和后缀)

四、动态库

首先我们需要把库文件全部编译成.o文件,这里与静态库不同,需要带上选项 -fPIC,形成与位置无关码。我们还是以上面的文件为例:

gcc -fPIC -c myadd.c -o myadd.o
gcc -fPIC -c myprintf.c -o myprintf.o

 

 动态库打包需要加上选项:-shared。

gcc -shared myprintf.o myadd.o -o lib.so

我们可以建立一个makefile,同时形成静态库和动态库。

 

然后我们发布:

接下来,我们就来使用一下我们自己制作的动态库。

 下图中,我们编译成功,且形成了可执行程序。 

但是,当我们运行可执行程序时,却失败了:

因为我们的lib目录下,既有动态库,也有静态库,所以gcc在编译时默认使用的是动态库。可是,既然我已经指明了库所在的路径,那为什么在运行可执行程序时还会动态链接失败呢?

原因就是:那只是在编译时,告诉了gcc编译器动态库在哪里,然后编译成功且形成了可执行程序,如果你在编译时没有告诉库在哪,编译就不会成功,且不会形成可执行程序。而我们运行可执行程序是由操作系统加载到内存来运行的,运行时也需要告诉操作系统库在哪里。我们还没有告诉操作系统动态库在哪里呢!!!

解决方法:

1、添加到环境变量里:把库路径添加到环境变量LD_LIBRARY_PATH

比如:我的动态库所在路径为:/home/zdl/mylib/output/lib

但是我们自己定义的环境变量只是本次登录有效,如果想永久有效只能修改环境变量的配置,但是比较麻烦。想永久有效,我们还有其他的方法。 

2、配置文件(/etc/ld.so.conf.d/):动态库进行对应搜索时可以采用自己定义conf文件找到动态库

直接在该路径 /etc/ld.so.conf.d/ 下创建一个以.conf为后缀的文件。

然后将动态库所在的路径添加到文件中即可。

最后,使用sudo ldconfig使文件生效。 

3、建立软链接直接找到对应的库

可以将库的路径建立软链接到 /lib64/ 路径下。

五、动静态库的加载

静态库:静态库是直接将自己的代码和数据拷贝到可执行程序中,然后随可执行程序一同加载到内存中。它们相当于已经是一体的了。静态库的代码随可执行程序的代码一起加载到程序地址空间的代码区。

动态库:动态库可以和可执行程序分批加载。

动态库加上fPIC选项形成位置无关码,采用相对编址的方法,在程序链接时对应库当中的偏移量添加到可执行程序,运行时一旦库加载进来,经过地址空间映射,把库映射到地址空间之后,库也就具备了起始地址,通过偏移地址和起始地址这样就可以找到访问的函数。

具体过程:可执行程序在运行时,如果遇到某处代码需要调用库的方法,库的代码和数据就会加载到物理内存中,然后将你需要使用的方法通过页表映射到共享区。然后代码直接到共享区去找,再通过页表找到物理内存中的具体方法,使用完后,代码继续向后执行,如又遇到库里的方法,就再去找。

如果有多个进程需要使用同一个库,那么其他的进程可以直接通过页表和物理内存中的代码直接建立联系。所以动态库加载一次就可以被多个进程共同使用了。

而静态库可能有多个程序用了C库,加载到内存时,内存里可能会存在很多份重复的代码。而动态链接不会出现重复的代码,减少内存占用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/620887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux操作】国产Linux服务管理操作

【Linux操作】国产Linux服务管理操作 前言SAMBA配置服务器端1. 安装相关包2. 配置/etc/samba/smb.conf,在此文件末尾添加如下内容,并保存退出。3. 创建/home/share并更改权限4. 启动samba服务 客户端• Windows客户端• 麒麟客户端 Telnet1、telnet语法2…

JOSEF约瑟端子排中间继电器 DZY-204 DC110V 导轨安装,板前接线

DZY系列端子排中间继电器 系列型号: DZY-101端子排中间继电器 DZY-104端子排中间继电器 DZY-105端子排中间继电器 DZY-301端子排中间继电器 DZY-106端子排中间继电器 DZY-401端子排中间继电器 DZY-204端子排中间继电器 一、 概述 DZY-204端子排中间继电器用于各种…

unity C#什么时候用“可空类型”

文章目录 例子1. **声明一个可空类型变量:**2. **给可空类型变量赋值:**3. **检查可空类型变量是否有值:**4. **转换与比较:**5. **使用null合并运算符:** 可空类型的重要意义1. **表示缺失或未知的值:**2.…

每日一博 - 使用APIFOX调测 @RequestBody标注的对象

文章目录 概述发送 post 请求步骤1.新建接口,设置为 post 请求2. 填写 URL 和参数3.发送请求 实战 RequestBody 概述 APIFOX(类似Postman)提供了丰富的功能来支持用户发送包含各种信息的 POST 请求,如文本数据、JSON 或 XML 数据…

云卷云舒:AI for DB、DB for AI

云卷云舒:算力网络云原生(下):云数据库发展的新篇章-CSDN博客https://blog.csdn.net/bishenghua/article/details/135050556 随着数据库和AI技术的分支同向演进,AI 和数据库间的关联越发紧密了。 大模型的演进发展&a…

element中el-cascader级联选择器只有最后一级可以多选

文章目录 一、前言二、实现2.1、设置popper-class和multiple2.2、设置样式 三、最后 一、前言 element-ui中el-cascader级联选择器只有最后一级可以多选,其它级只有展开子节点的功能,如下图所示: 可以观察到最后一级的li节点上没有属性aria-…

java基础知识点系列——基础语法(三)

java基础知识点系列——基础语法(三) 注释 注释概述 注释是在程序指定位置添加的说明性信息。注释不参与程序运行,仅起到说明作用。 注释分类 单行注释,格式:// 注释信息多行注释,格式:/* …

面向对象的三大特征之二:继承 --java学习笔记

什么是继承? 关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系 继承的特点:子类能继承父类的非私有成员(成员变量、成员方法)继承后对象的创建:子类的对象时由子类、父类共同完成的 代码演示&am…

Hex Editor的使用教程(VS Code)

Hex Editor(十六进制编辑器)是一种用于查看和编辑计算机文件的低级别编辑工具。与常规文本编辑器不同,它允许用户直接查看和修改文件的二进制数据。在 Hex Editor 中,数据通常以十六进制(hex)格式显示&…

Qt/QML编程学习之心得:使用camera摄像头(35)

汽车应用中,camera起到了越来越多的作用,数字化的作用,这点无可争议,而作为GUI设计工具,如何让Camera类的应用能更好的发挥作用呢? You can use Camera to capture images and movies from a camera, and manipulate the capture and processing settings that get appl…

EI论文复现:考虑多能互补的综合能源系统/虚拟电厂/微电网优化运行程序代码!

本程序参考EI论文《基于多能互补的热电联供型微网优化运行》,文章通过储能设备解耦热电联系,建立基于多能互补的综合能源系统/虚拟电厂/微电网优化运行模型。模型包含系统供给侧的多能互补协调与需求侧的综合能源响应两个方面,使供给侧通过能…

Grind75第9天 | 733.图像渲染、542.01矩阵、1235.规划兼职工作

733.图像渲染 题目链接:https://leetcode.com/problems/flood-fill 解法: 可以用深度优先搜索和广度优先搜索。 深度优先搜索。每次搜索到一个方格时,如果其与初始位置的方格颜色相同,就将该方格的染色,然后继续对…

Qt构建MSVC2015环境过程

Qt构建MSVC2015环境过程 前言 之前用的Qt都是基于默认的MinGW编译器,由于目前工作的QT界面主要是跑在X86上,所以记录一下Qt配置MSVC2015的配置过程。根据查阅了解以后,个人理解的MinGW跟MSVC的区别在于前者主要是用于跨平台程序构建&#x…

Redis命令 - Hashes命令组常用命令

1、HSET key field value 设置 key 指定的哈希集中指定字段的值。 HSET key field value 返回值:1代表field是一个新的字段。0代表field已存在 如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段在哈希集中存在,它将…

软件需求分析报告—word

技术要求 1.1接口要求 1.2可靠性,稳定性,安全性,先进性,拓展性,性能,响应。 2.系统安全需求 2.1物理设计安全 2.2系统安全设计 2.3网络安全设计 2.4应用安全设计 2.5用户安全管理 进主页获取更多资料

靶场实战(15):OSCP备考之VulnHub STAPLER

打靶思路 资产发现 主机发现服务发现漏洞发现(获取权限) 21端口/FTP服务 组件漏洞口令漏洞139端口/SMB服务 组件漏洞口令漏洞666端口/doom服务 组件漏洞其它漏洞80端口/HTTP服务 组件漏洞URL漏洞12380端口/HTTP服务 组件漏洞URL漏洞12380端口/HTTPS服务 …

gitee创建远程仓库并克隆远程仓库到电脑

1、首先点加号新建一个仓库 2、输入仓库名,路径会自动填充,填写简单的仓库介绍,先选择私有,在仓库创建之后,可以改为开源 3、打开建好的仓库 4、复制仓库链接 5、打开一个文件夹(想要存储远程仓库的地址),在…

C# 图解教程 第5版 —— 第24章 预处理指令

文章目录 24.1 什么是预处理指令24.2 基本规则24.3 符号指令(#define、#undef )24.4 条件编译(#if、#else、#elif、#endif)24.5 条件编译结构24.6 诊断指令(#warning、#error)24.7 行号指令(#li…

Web后端开发

一、Maven 1.1 简介 1.2 作用 1.3 流程 通过各种插件实现项目的标准化构建。 1.4 安装 1.5 配置环境 1.5.1 当前工程环境 1.5.2 全局环境 1.6 创建 Maven项目 1.7 导入项目 1.8 依赖管理 1.8.1 依赖配置 1.8.2 依赖传递 pom.xml——右键——Diagrams——show dependen…