深入理解Linux中的动态库与静态库

 

                                               🎬慕斯主页修仙—别有洞天 

                                              ♈️今日夜电波:I Wish My Mind Would Shut Up—Ivoris

                                                                0:21━━━━━━️💟──────── 2:04
                                                                    🔄   ◀️   ⏸   ▶️    ☰  

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

动态库与静态库的概念

动态库与静态库的制作

引入

生成静态库

生成动态库

动态库与静态库的使用

静态库的使用

在系统中安装这个库

拿到上面所提到的库该怎么用

动态库的使用

方法一:头文件以及库文件安装到系统里

方法二:建立软连接来找动态库

方法三:LD_LIBRARY_PATH

方法四:直接更改系统关于动态库的配置文件


动态库与静态库的概念

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

        动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

        一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)

        动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

动态库与静态库的制作

引入

        在写C/C++代码时,我们经常会做到头文件与源文件的分离,后续要使用对应的类或者函数,定义一下头文件,再调用即可。这和我们调用C/C++中的库是类似的,只不过我们调用是使用 "" 而内置的库使用的是 <> 。动静态库的制作跟调用我们自己的头文件是类似的,只不过我们将众多的源文件封装在了一个文件中,头文件则没有改变。需要注意的是:这些文件中没有主函数,因为这会导致后续使用的冲突。

        如下我们定义几个头文件与源文件分离调用的例子:

#pragma once

#include <stdio.h>


extern int Add(int,int);
#include "Add.h"


int Add(int x,int y)
{
    return x + y;
}
#pragma once

#include <stdio.h>


extern int Sub(int,int);
#include "Sub.h"


int Sub(int x,int y)
{
    return x - y;
}
#include "Add.h"
#include "Sub.h"

int main()
{
    int x = 114;
    int y = 514;

    printf("%d+%d=%d\n", x, y, Add(x, y));
    printf("%d-%d=%d\n", x, y, Sub(x, y));

    return 0;
}

        如下图所示,我们将头文件与源文件编译生成了可执行程序,需要注意的是:我们在这里并没有说用哪个头文件,那怎么还能编译通过呢?这是由于头文件在当前路径下,编译器是能够自动找到的。(头文件的查找是在当前目录或者指定目录下)如下:

        当然,我们都知道每一个文件都需要经过预处理、编译、汇编、链接的。而当我们使用多文件操作形成可执行程序的时候,其实是不建议向上面一样直接生成可执行程序的,通常应该是先生成.o文件,然后再进行链接的操作这也是为啥我们经常会看到很多.obj文件的原因,因为未来我们可以通过组合这些.o可生成多个指定的文件。

        如下我们通过一个Makefile脚本生成对应的.o文件:

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

        对以上命令的解析:

  • %.o:%.c:表示当一个以.c为后缀的文件发生变化时,需要重新生成一个以.o为后缀的目标文件。其中,%是一个占位符,表示任意字符序列。
  • gcc -c $<:表示使用gcc编译器将$<指定的源文件(即当前目标文件的前缀部分)编译成目标文件。$<是一个特殊的变量,表示依赖项列表中的第一个元素。即:每一个.c都会依次生成.o文件。
  • Test:Add.o Sub.o testmain.o:表示目标文件的依赖关系。在这个例子中,Test依赖于Add.o、Sub.o和testmain.o这三个目标文件。
  • gcc -o $@ $^:表示使用gcc编译器将依赖项列表中的所有目标文件(即$^)链接成一个可执行文件,并将其命名为$@指定的名称。$@是一个特殊的变量,表示目标文件的名称。
  • .PHONY:clean:表示clean不是一个实际的目标文件。它通常用于定义一些特殊的伪目标,如clean、install等。这些伪目标并不对应于任何实际的文件,而是用于执行一些特定的操作,例如清理编译生成的文件或安装软件包。
  • clean::定义了一个名为clean的伪目标。
  • rm -f *.o Test:表示删除所有的目标文件(以.o为后缀的文件)以及可执行文件Test。

        实际上,我们只需要将这些.o文件以及头文件打包给别人,如果别人要使用我们的.o文件,他只需要将自己的源文件编译成.o文件然后再一起链接即可这个打包的过程大致就是生成库的过程,接下来我们就分动态库以及静态库两种“打包方式”进行叙述。

生成静态库

        生成静态库的命令:ar命令在Linux中用于管理静态库

该命令提供了多个选项来处理归档文件,以下是一些常用的参数:

  • -t 显示归档文件中所包含的文件列表。
  • -x 从归档文件中提取指定的文件。
  • -r 向归档文件中添加一个或多个文件。
  • -c 表示创建新的归档文件
  • -d 从归档文件中删除指定的文件。
  • -m 在归档文件中移动或重排文件的顺序。
  • -p 打印归档文件中指定文件的内容。
  • -q 将文件追加到归档文件的末尾。
  • -a 将文件插入到归档文件中指定文件之后。

        通常我们使用以下命令来创建静态库:

ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)

        需要注意的是:静态库取名字是有规则的,必须按"lib名.a"来取名,后续跟上对应的.o文件即可

        如下根据上述我们更改上面的Makefile脚本:

   %.o:%.c
     gcc -c $<
   static-lib=libmymath.a
   $(static-lib):Add.o Sub.o
     ar -rc $@ $^
   .PHONY:clean
   clean:
   rm -f *.o *.a 

        接着我们将打包好的静态库以及头文件再次打包放到文件中,这就可作为“发布”的操作。

   %.o:%.c
     gcc -c $<
   static-lib=libmymath.a
   $(static-lib):Add.o Sub.o
     ar -rc $@ $^
    .PHONY:output
    output:
      mkdir -p mymath_lib/include
      mkdir -p mymath_lib/lib
      cp -f *.h mymath_lib/include
      cp -f *.a mymath_lib/lib       
   .PHONY:clean
   clean:
   rm -rf *.o *.a mmath_lib

        再使用tar czf 命令打包这个文件就可给别人下载了。别人使用tar xzf 命令就可解压得到这个库了。

生成动态库

shared: 表示生成共享库格式

fPIC:产生位置无关码(position independent code)

库名规则:libxxx.so

        如下我们通过一个Makefile脚本生成对应的.so文件:

   %.o:%.c
     gcc -fPIC -c $<
   dy-lib=libmymath.so
   $(dy-lib):Add.o Sub.o
     gcc -shared -o $@ $^
   
   #Test:Add.o Sub.o testmain.o
   # gcc -o $@ $^ 
   
   .PHONY:output
   output:
   mkdir -p mymath_lib/include
   mkdir -p mymath_lib/lib
   cp -f *.h mymath_lib/include
   cp -f *.so mymath_lib/lib
  
   .PHONY:clean
   clean:
     rm -rf *.o *.so mymath_lib   

动态库与静态库的使用

静态库的使用

        如下,我们可见这个目录下已经拥有了打包过后的静态库以及头文件,但是还是报错了,这是因为我们没有正确的使用静态库!

        我们自己写的库,实际上叫做第三方库,编译器是不认可这个库的,我们在使用这个库的时候需要使用 -l 选项指定链接一个库。如果还是不认识就需要再使用 -L 告诉在哪个路径下,这里带的是当前路径也就是 . 。

        使用ldd a.out列出a.out文件所依赖的所有动态链接库及其路径,我们发现并没有我们自己的库,因为静态库已经拷贝到可执行程序中了,我们是查不到的。当然,gcc默认是链接动态库,也可动静混和、带static选项使用静态库

在系统中安装这个库

        我们只需要将对应的头文件以及库放到系统中的这些目录下即可安装成功。如下:头文件:/usr/include,库:/usr/lib64。

拿到上面所提到的库该怎么用

        也就是如下的文件:

        我们可以按照上面提到的安装到系统中,当然也可以在指定路径使用对应的库。使用 -I 选项表示我们不仅需要在系统目录中找对应的头文件还需要在指定路径找对应的头文件。结合上述链接静态库可得如下:

        需要注意的是:如果我们将对应的头文件以及库安装到系统目录里了,只需要带 -l 即可。

动态库的使用

方法一:头文件以及库文件安装到系统里

        需要注意的是:要加上-l 选项指定第三方库。(最推荐的做法使用第三方库)

方法二:建立软连接来找动态库

        静态库如果在当前路径下是不会被找到的,动态库如果在当前路径下是可以找到的,因此我们可以通过建立软连接来使用动态库当然。后续可以将软连接添加到系统目录中。

方法三:LD_LIBRARY_PATH

        通过改变环境变量来使得动态库可以被找到。当然这只是临时生效的,只要重启shell就会消失,如果要永久生效需要更改配置文件这里不多阐述。

方法四:直接更改系统关于动态库的配置文件
/etc/ld.so.conf.d/

        里面是系统动态库加载相关的文件。可以看到该路径下的文件存的仅仅是一个路径,系统就是通过这些路径来找到对应的动态库的:

        在该路径下创建对应的.conf文件:

        将对应的路径贴到文件中即可:

        通常会及时生效,如果没生效可使用sudo inconfig 刷新或者也可重启系统。


                         感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                        给个三连再走嘛~  

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java基于沙箱环境实现支付宝支付

一、支付宝沙箱环境介绍 沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境&#xff0c;开发者在沙箱环境中调用接口无需具备所需的商业资质&#xff0c;无需绑定和开通产品&#xff0c;同时不会对生产环境中的数据造成任何影响。合理使用沙箱环境&#xff0c;可以…

【深度学习:集中偏差】减少计算机视觉数据集中偏差的 5 种方法

【深度学习&#xff1a;集中偏差】减少计算机视觉数据集中偏差的 5 种方法 有偏差的计算机视觉数据集会导致哪些问题&#xff1f;如何减少计算机视觉数据集中偏差的示例观察并监控带注释样本的类别分布确保数据集代表模型适用的人群明确定义对象分类、标记和注释的流程为标签质…

鸿蒙开发-UI-布局-列表

鸿蒙开发-UI-布局 鸿蒙开发-UI-布局-线性布局 鸿蒙开发-UI-布局-层叠布局 鸿蒙开发-UI-布局-弹性布局 鸿蒙开发-UI-布局-相对布局 鸿蒙开发-UI-布局-格栅布局 文章目录 前言 一、基本概念 二、开发布局 1.布局约束 2.开发布局 三、应用特性 1.列表数据显示 2.列表数据迭代 3.列…

216. 组合总和 III - 力扣(LeetCode)

题目描述 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 输入示例 k 3, n 7输出示例 [[1,2,…

云风网(www.niech.cn)个人网站搭建(八)服务器部署接口测试请求

将之前测试的 html 文件中http://127.0.0.1:8090/地址改成云服务器外网地址&#xff0c;同时需要安全组需要开放 8090 端口 接下来根据步骤进行测试 一、注册用户 注册请求成功&#xff0c;接下来查看数据库&#xff0c;数据库表也更新了数据 二、登录账户 账号登录成功&a…

cdn-工作笔记

问题 pc端打开login页面很慢&#xff0c;进入后切换菜单速度很快&#xff0c;但小程序打开速度正常&#xff0c;就接排除了网络和接口的问题 原因 发现是 这个接口影响了 cdn该充钱了 或者 替换一个 解决 这个项目原本用的是Staticfile CDN 想换一个 打开网址BootCDN - B…

数据仓库-相关概念

简介 数据仓库是一个用于集成、存储和管理大量数据的系统。它用于支持企业决策制定过程中的数据分析和报告需求。数据仓库从多个来源收集和整合数据&#xff0c;并将其组织成易于查询和分析的结构。 数据仓库的主要目标是提供高性能的数据访问和分析能力&#xff0c;以便…

Unity - 简单音频视频

“Test_04” 音频 使用AudioTest脚本控制Audio Source组件&#xff0c;在脚本中声明"music"和"se"之后&#xff0c;在unity中需要将音频资源拖拽到对应位置。 AudioTest public class AudioTest : MonoBehaviour {// 声明音频// AudioClippublic AudioC…

Java 基础 - 反射

Java 基础 - 反射 文章目录 Java 基础 - 反射1 什么是类对象2 获取类对象的方法3 反射通用操作【重点】3.1 常见方法3.2 通用操作 4 内省 1 什么是类对象 类的对象&#xff1a;基于某个类 new 出来的对象&#xff0c;也称为实例对象。 类对象&#xff1a;类加载的产物&#x…

ThinkPHP5.0.0~5.0.23路由控制不严谨导致的RCE

本次我们继续以漏洞挖掘者的视角&#xff0c;来分析thinkphp的RCE 敏感函数发现 在调用入口函数&#xff1a;/ThinkPHP_full_v5.0.22/public/index.php 时 发现了框架底层调用了\thinkphp\library\think\App.php的app类中的incokeMethod方法 注意传递的参数&#xff0c;Refle…

期末考试发等级发成绩,就用易查分!

期末考试后&#xff0c;学校老师如何发布私密成绩&#xff1f;易查分可以轻松创建等级、成绩查询系统&#xff0c;让家长仅看到自己孩子成绩。 支持查询后留言反馈&#xff0c;电子签名确认签收等高级功能&#xff0c;节省老师沟通时间&#xff0c;大大提升工作效率。 &#x1…

小白水平理解面试经典题目LeetCode 594 最大和谐字符串

594 最大和谐字符串 这道题属于字符串类型题目&#xff0c;解决的办法还是有很多的&#xff0c;暴力算法&#xff0c;二分法&#xff0c;双指针等等。 题目描述 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。 现在&#xff0c;给你一个整数数组 nums …

数据结构课程设计 仓储管理系统

仓储管理系统 【基本功能】 把货品信息表抽象成一个线性表&#xff0c;货品信息&#xff08;包括ID、货品名、定价、数量等&#xff09;作为线性表的一个元素&#xff0c;实现&#xff1a;按ID、货品名分别查找某货品信息&#xff08;包括ID、货品名、定价、数量等&#xff0…

【产品设计】TO B 搜索和筛选的多种使用场景

&#xff1a;随着B端项目越来越普及&#xff0c;企业也逐渐意识到产品的视觉效果、功能的好用性及用户体验的友好性等等。 最近B端一词在互联网中的呼声很高&#xff0c;对于B端和C端而言&#xff0c;面向的用户是不一样的&#xff0c;常用的硬件设备也有所区分&#xff0c;C端…

java---多线程

多线程 线程:一个顺序的单一的程序执行流程就是一个线程。代码一句一句的有先后顺序的执行。 多线程:多个单一顺序执行的流程并发运行。造成"感官上同时运行"的效果。 并发: 多个线程实际运行是走走停停的。线程调度程序会将CPU运行时间划分为若干个时间片段并 尽可…

遍历子网所有ip地址,寻找空闲ip

在cmd窗口下输入如下代码&#xff1a; for /l %i in (1,1,255) do ping -n 1 -w 60 10.183.27.%i | find "Reply" >> d:\pingall27.log 得到如下结果 上图中&#xff0c;有reply的代表该IP已经被占用。但是观察红框中 22-->25之间缺少23 24 则说明23/24 是…

Python源码46:海龟画图turtle画坤坤

---------------turtle源码集合--------------- Python教程91&#xff1a;关于海龟画图&#xff0c;Turtle模块需要学习的知识点 Python源码45&#xff1a;海龟画图turtle画雪容融 Python源码44&#xff1a;海龟画图turtle&#xff0c;画2022卡塔尔世界杯吉祥物 Python教程…

90. 子集 II - 力扣(LeetCode)

题目描述 给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列。 输入示例 nums [1,2,2]输出示例 [[],[1],[1…

生命在于学习——Firewalled学习

一、Firewalld是什么&#xff1f; Firewalld是一种动态防火墙管理器服务&#xff0c;相较于传统的静态防火墙管理工具iptables&#xff0c;它具有更多优势。Firewalld可以实现无需重新加载所有规则&#xff0c;只需保存和更新变更部分即可生效&#xff0c;从而减少对系统的影响…

Message queue 消息队列--RabbitMQ 【基础入门】

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是平顶山大师&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Message queue 消息队列--RabbitMQ 【基础入门…