动态库和静态库的理解 Linux

news2024/9/29 19:16:25

其实库文件里面的内容就是函数的实现方法,向我们包含的头文件其实就是函数的生命,而我们编译链接程序时会自动加载库文件,最终形成可执行程序。其实我们在编译链接时不仅仅会将文件的库文件加载进来,其实头文件也是需要加载进来的,只不过也是自动加载的。

静态库

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

模拟实现静态库

其实库文件的形式都是.c文件编译成的.o目标二进制文件,然后全部打包给我们用户进行使用。如果我们用户的main函数中使用了对应库文件的函数方法,那么我们用户可以将main函数编译成.o文件,再将所有.o文件链接起来形成可执行程序即可实现。

现在我们开始模拟实现库文件,首先就是实现函数生成.o文件,所以此时的指令就是gcc -c test.c -o test.o,其实后面不接-o也是没问题的,会自动生成同名的.o文件,所以此时就十分轻松。

此时拿一个add函数和sub函数举例,实现函数声明定义分离的形式:

"add.h"

#pragma once
#include<stdio.h>
int add(int ,int);

"sub.h"

#pragma once 
#include<stdio.h>
int sub(int,int);

"add.c"

#include"add.h"
int add(int x,int y)
{
    return x+y;
}

"sub.c"

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

"main.c"

#include"add.h"
#include"sub.h"
int main()
{
    printf("%d+%d=%d\n",3,4,add(3,4));
    printf("%d-%d=%d\n",3,4,sub(3,4));

    return 0;
}


生成.o文件和.exe的makefile:(#是注释)

test.exe:test.o add.o sub.o
	gcc -o $@ $^

%.o:%.c  # %类似于通配符,会查找当前目录下的所有后缀为.c的文件,并且会生成相同文件名的.o文件
	gcc -c $< # $<相当于一个个的.c文件各自拿过来编译

.PHONY:clean
clean:
	rm -f test.exe

 

 而生成静态库的指令就是:ar -rc  xxx.a xx.o x.o  其中rc表示(replace and create)

生成库文件的makefile:

libmymath.a:*.o
	ar -rc $@ $^  #生成静态库
.PHONY:clean
clean:
	rm -f *.a

最后就是将库文件和我们的main.c文件链接生成可执行程序了。

链接生成可执行程序:

gcc main.c -I ./ -l mymath -L ./
-I 指定头文件路径(当前路径的话会默认查找)
-L 指定库路径
-l 指定库名

首先我们要了解一下后面的指令参数,-l和-L,而我们在没有链接我们实现的静态库时,而是gcc编译器会自动的链接C语言的库,所以就不需要这两个指令参数。在此我们要知道我们写的库叫做第三方库,所以在形成可执行程序的时候需要链接我们的第三方库,而且一般还要指明路径。并且我们链接的库名称是需要去掉前缀lib和后缀.a的。

默认搜索库和头文件: 

在Linux中我们进行编译C语言文件的时候系统默认会在/usr/include中搜索头文件的,而在库文件都是在/lib64里搜索的。所以我们也可以将我们自己的的头文件和库文件拷贝到对应的路径下,那么在之后编译链接时就会直接默认像路径中寻找对应库文件链接生成可执行程序。

 

动态库

动态库是一种在运行时被可执行文件引用的库文件。它是独立于可执行文件的外部文件,可以被多个程序共享使用。动态库的文件扩展名一般为.so(在Windows下为.dll)。动态库的主要特点是在程序运行时动态加载,可以节省系统内存,同时也方便了库的更新和维护。

动态库模拟实现

其实和静态库的操作是没啥区别的,只不过有些指令的参数不同。首先还是生成.o文件,然后再将.o文件生成动态库。

makefile的实现:

libmymath.so:add.o sub.o
	gcc -shared -o $@ $^ # 生成共享库格式
%.o:%.c
	gcc -fPIC -c $< # 产生位置无关码,也就是相对编址的方式

.PHONY:output # 发行
output:
	mkdir -p mymath/include
	mkdir -p mymath/lib 
	cp -f *.h mymath/include
	cp -f *.so mymath/lib 

.PHONY:clean
clean:
	rm -rf *.o *.so mymath

 将发行的文件mymath拷贝到一个新的目录文件下:

 

链接生成可执行程序:

gcc main.c -l mymath -L mymath/lib -I mymath/include
-l :指定库名称(去掉前缀lib和后缀.so)
-L :库的所在路径
-I :头文件所在路径

 运行可执行程序:

但是我们其实还是无法直接进行运行的。

ldd指令查看所需动态库: 

 因为对于静态库来说静态库会被整个复制到可执行文件中,所以一旦编译成功了之后就和静态库没什么关系了,可执行程序也就可以直接运行,所以运行期间也不需要查找静态库而对于动态库就不一样了,动态库和可执行程序是分离的,也就是两个不同的文件,所以在运行我们可执行程序的时候就要将我们的程序和动态库都加载到内存中才可以运行起来

动态库运行时的解决方法

  1. 直接将我们的第三方动态库安装(拷贝)到系统默认的动态库/lib64目录下。也可以顺带将头文件拷贝到/usr/include下,那么我们在下次gcc编译的时候就只需要带上链接动态库的文件名就行了。
  2. 将库文件拷贝到与main.c文件在同一个目录路径下(因为动态链接时,运行可执行程序时不仅仅会在/lib64查找库文件,也会默认在当前目录下查找库文件)其实也可以通过创建软硬链接的方式进行:(软硬链接后的名称一定要与所需动态库同名
  3. 直接更改系统中关于动态库的配置文件(系统中配置文件的位置在/exc/ld.so.conf.d/中,所以我们需要在该路径下touch一个文件,然后我们vim文件,直接将我们的动态库绝对路径写入文件中即可,最后ldconfig命令刷新一下就可以。而且该配置文件内容始终有效)
  4. 将我们实现的库拷贝到环境变量LD_LIBRARY_PATH中(因为我们执行可执行程序时,系统除了会在默认路径下帮我们加载库文件外,还会在该环境变量中搜索对应的动静态库。但是只是在内存中写入,所以下次使用就不存在了)
    export LD_LIBRARY_PATH = $LD_LIBRARY_PATH : (我们库所在的路径)

我们在链接动态库的程序在运行期间也是需要库文件的,其实本质就是在编译期间会形成符号表,记录函数名与函数在库里的地址映射关系,而最后运行期间加载到内存的时候,如果主函数调用了动态库中的函数时,就会找到函数地址,但是此时需要将库文件也一同运行到内存中,这样才可以找到需要调用的函数。

 

gcc默认都是链接动态库 :

如果我们同一个库的目录文件下提供了动静态两种库,那么在gcc编译时会默认使用动态库,除非后面带上 -static选项才会使用我们的静态库。 

gcc main.c -l mymath -L mymath/lib -I mymath/include  //默认动态链接
gcc main.c -l mymath -L mymath/lib -I mymath/include -static //强制静态链接该库

 

 使用外部库

  1. 安装库。可以通过yum install -y等指令进行安装外部第三方库。
  2. 将头文件和库文件分别安装到对应的默认加载路径里。如果yum自动安装了的话就不用了
  3. gcc编译。不要忘记加上 "-l 库名"

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

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

相关文章

工作进入第八年,还在成长的一年

这一年没有写太多的技术博客&#xff0c;是因为工作内容发生了较大的改变&#xff0c;岗位也发生了调整。随着ChatGPT的爆火&#xff0c;无论从公司的领导层&#xff0c;还是从现场的用户&#xff0c;人工智能算是被彻底颠覆了&#xff0c;每个人对生成式人工智能的期待太高&am…

架构篇24:排除架构可用性隐患的利器-FMEA方法

文章目录 FMEA 介绍FMEA 方法FMEA 实战小结 前面的专栏分析高可用复杂度的时候提出了一个问题&#xff1a;高可用和高性能哪个更复杂&#xff0c;根据墨菲定律“可能出错的事情最终都会出错”&#xff0c;架构隐患总有一天会导致系统故障。因此&#xff0c;我们在进行架构设计的…

Intel Atom + Artix-7 100T FPGA,CompactRIO单板控制器

模拟和数字I/O&#xff0c;RMC&#xff0c;DisplayPort&#xff0c;1.33 GHz双核CPU&#xff0c;1 GB DRAM&#xff0c;4 GB存储容量&#xff0c;Artix-7 100T FPGA&#xff0c;CompactRIO单板控制器 CompactRIO控制器是搭载了实时处理器和用户可编程FPGA的嵌入式控制器。其产…

低代码(Low-Code)技术简化开发难度,快速搭建应用

目录 一、低代码技术定义 二、低代码技术优势 1.提高企业的工作效率 2.降低企业的开发成本 3.提高应用程序和业务流程的质量 三、稳定性和生产率的最佳实践 三、最后 随着数字化时代的到来&#xff0c;低代码&#xff08;Low-Code&#xff09;技术已经成为了企业数字化转…

如何使用Docker本地部署Jupyter Notebook并结合内网穿透实现远程访问

&#x1f4d1;前言 本文主要是Linux下通过使用Docker本地部署Jupyter Notebook并结合内网穿透实现远程访问的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;…

别不信❗️你离数据专家只差一个CDMP证书

1⃣️为什么选择CDMP证书&#xff1f; &#x1f31f;&#x1f31f;亲爱的朋友们&#xff0c;如果你在寻找一个能让你在数据管理领域大展拳脚的证书&#xff0c;那么CDMP&#xff08;Certified Data Management Professional&#xff09;证书就是你的不二之选&#xff01;&#…

JavaScript进阶:WebAPIs重点知识整理2

目录 1 对节点的相关操作 1.1 查找节点 1.1.1 查找节点的父节点 1.1.2 查找节点的子节点 1.1.3 查找节点的兄弟节点 1.2 新增节点&#xff08;先创建&#xff0c;后追加&#xff09; 1.3 克隆节点 1.4 删除节点 2 M 端&#xff08;移动端&#xff09;事件 3 JS清空表…

hadoop集群规划部署

一、集群规划 三台硬件资源&#xff0c;部署hadoop版本&#xff0c;hadoop-3.3.5 &#xff0c;部署后配置文件。 Hadoop配置文件分两类&#xff1a;默认配置文件和自定义配置文件。 hadoop102hadoop103hadoop104HDFS NameNode DataNode DataNode SecondaryNameNode DataN…

深度强化学习Task3:A2C、A3C算法

本篇博客是本人参加Datawhale组队学习第三次任务的笔记 【教程地址】 文章目录 Actor-Critic 算法提出的动机Q Actor-Critic 算法A2C 与 A3C 算法广义优势估计A3C实现建立Actor和Critic网络定义智能体定义环境训练利用JoyRL实现多进程 练习总结 Actor-Critic 算法提出的动机 蒙…

Matlab|基于改进遗传算法的储能选址定容(可任意设定储能数量)

目录 主要内容 部分代码 结果一览&#xff08;以3个储能为例&#xff09; 下载链接 主要内容 该模型采用改进遗传算法优化配电网系统中储能选址位置和容量&#xff0c;程序以IEEE33节点系统为分析对象&#xff0c;以网损最小为目标&#xff0c;采用matpower实现系…

谷粒商城-微服务架构图

整体架构 分布式划分图

蓝牙运动耳机什么牌子的好?蓝牙运动耳机品牌排行榜前十名

​运动耳机是耳机中使用场景最广泛的一类&#xff0c;特别适合户外运动、健身和骑行等场景。在众多运动耳机中&#xff0c;哪一款更值得入手呢&#xff1f;今天我将向大家推荐几款相当不错的运动耳机&#xff0c;它们不仅音质上乘&#xff0c;还能满足不同运动场景的需求。 1.…

ozon促销活动100+店铺如何多店铺批量加入活动产品?ozon促销产品怎么删除?

很多Ozon卖家为实现店铺引流&#xff0c;会参与许多官方促销活动&#xff0c;如果每个活动都需要单独管理&#xff0c;会消耗不少的时间成本&#xff0c;操作起来也会非常困难。 尤其是随着运营店铺数量的增加&#xff0c;多个店铺多个促销活动来回切换管理&#xff0c;不仅耗…

modbus poll测试工具测试modbus tcp与PLC设备连接使用方法

socket默认端口是502&#xff0c;socket连上之后&#xff0c; 按照modbuspoll工具设置的读写参数 生成的RTU命令格式去组装读PLC的设备数据 modbuspoll工具配置&#xff0c;以v9.9.2中文破解版为例&#xff1a; 首先点连接菜单&#xff08;connection&#xff09;建立连接&…

Database history tablesupgraded

zabbix升级到6之后&#xff0c;配置安装完成会有一个红色输出&#xff0c;但是不影响zabbix使用&#xff0c;出于强迫症&#xff0c;找到了该问题的解决方法。 Database history tables upgraded: No. Support for the old numeric type is deprecated. Please upgrade to nume…

C++:优先队列-Priority_queue

目录 1.关于优先队列 2.priority_queue的使用 1.构造方法 2.empty();判空 3.size(); 4.top(); 5.push(val); 6.pop(); 3.优先队列模拟实现 4.用优先队列解决数组中第K个大的元素 1.关于优先队列 在C中&#xff0c;可以使用STL&#xff08;标准模板库&#xff09;中的p…

【第十五课】数据结构:堆 (“堆”的介绍+主要操作 / acwing-838堆排序 / 时间复杂度的分析 / c++代码 )

目录 关于堆的一些知识的回顾 数据结构&#xff1a;堆的特点 "down" 和 "up"&#xff1a;维护堆的性质 down up 数据结构&#xff1a;堆的主要操作 acwing-838堆排序 代码如下 时间复杂度分析 确实是在写的过程中频繁回顾了很多关于树的知识&…

C++基础语法和用法

文章目录 1.hello world2.引入namespace(命名空间/域问题)3.输入输出4.缺省参数/默认参数5.函数重载6.引用7.内联函数8.auto关键字&#xff0c;基于范围的for循环&#xff0c;空指针NULL8.1 auto8.2 基于范围的for循环8.3 nullptr 1.hello world #include <iostream> us…

diffusion入门

1. diffusion model 概念 https://zhuanlan.zhihu.com/p/638442430 这篇博客写得很好&#xff0c;顺便做一点笔记记录一下。 原博客附带的代码也很清晰易懂。 1.1 前向过程 后一个过程等于前一个结果的均值乘上sqrt(1-beta_t), 再加上方差beta_t的噪声。 这样下去可以得到 x…

EasyCVR视频融合平台铁路抑尘喷洒监控系统视频搭建方案

一、建设背景与需求分析 随着我国铁路建设的迅猛发展&#xff0c;铁路抑尘喷洒设备质量监控系统在技术和管理方面都取得了显著的进步&#xff0c;面临安全压力也随之加大。为了确保铁路运输的安全和稳定&#xff0c;车站监控室、喷洒区域、操作间以及安全防护区域等关键区域都…