Linux动静态库

在这里插入图片描述

文章目录

    • 1. 静态库
    • 2. 动态库
    • 3. 动态库的加载

本章代码gitee仓库:动静态库

1. 静态库

Linux开发工具gcc/g++篇,此篇文章讲过动静态库的基本概念,不了解的可以先看一下这篇文章。

现在我们先来制作一个简单的静态库

mymath.h

#pragma once#include<stdio.h>extern int meyerrno;
int add(int x,int y);
int sub(int x,int y);
int mul(int x,int y);
int div(int x,int y);

mymath.c

#include"mymath.h"int myerrno = 0;
int add(int x,int y)
{return x+y;
}
int sub(int x,int y)
{return x-y;
}
int mul(int x,int y)
{return x*y;
}
int div(int x,int y)
{if(y == 0){myerrno = -1;return -1;}return x/y;
}

我们要是想把我们这个方法提供给不然用,2种方法

  1. 直接将源文件给别人

  2. 将源代码打包成库 -> 库+.h文件

    这里头文件是是必须要给的,这个头文件就相当于我们库的一份说明书

别人要使用我们的方法,其就是将我们的这个.c文件全部编译成.o,然后链接起来形成可执行,现在我们不给源文件,我们自己先编译成.o,然后全部打包给人家,人家就只需要编译自己的.c文件,然后结合我们这个打包文件即可

指令ar -rc lib.o test1.o test2.o将编译好的.o文件打包起来

这时候就已经将库打包好了,要将其发布,我们只需再包装一下即可

将这个打包好的库,使用一下

image-20231115193958352

我们这里包含完整路径,告诉这个头文件在哪儿,但一般我们都是直接包含头文件的名称,不会带上路径

#include"mymath.h"
int main()
{printf("1+1=%d\n",add(1,1));return 0;
}

但是这样的话,编译就不通过了,找不到这个头文件

在gcc中,它会在当前目录和系统里面搜索,这个当前目录指的是和源代码在同一级目录下

image-20231115194238561

我们可以采用gcc main.c -I ./lib/include,告诉gcc去这个路径里面找我们的头文件

这里的路径不需要再跟上我们的mymath.h,因为我们代码中已经包含了

image-20231115194540196

再继续编译,这里没有报找不到头文件的错误,而是报的的是链接错误

这里我们可以测试一下,让他生成目标文件,不进行链接,这里是没有问题的

image-20231115194741297

这是因为找不到我们打包好的静态库,这个原因也是gcc只会去默认的库路径或者是当前目录找库。

所以我们还要带上gcc main.-I ./lib/include/ -L ./lib/mymathlib/,告诉gcc去这个路径找,执行发现,还是错误

image-20231115195408595

报错还是一样,这里是因为我们并没告诉gcc,要链接哪个库,我们后面还要跟上gcc main.c -I ./lib/include/ -L ./lib/mymathlib/ -l mymath

小写-l后面简易紧跟库名称,库的真实名称是去掉前缀,去掉后缀

image-20231115200549943

这些选项带着看着有点冗余,我们之前写的代码是纯C的代码,gcc能在系统中找到这些动静态库。

而我们现在用的库,属于第三方库,所以要带上这些选项,如果想这样做,我们可以将这个库的头文件拷贝到系统的include,将库文件拷贝到系统的lib64目录中,然后指定-l编译,如果不想这样,我们可以建立软链接

Tips:

我们这里写的库中,对除零错误进行了判定

printf("11/0 = %d errno = %d\n",div(11,0),myerrno);

这段代码的myerrno并没有改变,这是因为传参是从右向左传递的,传递myerrno的时候,div函数还未调用,所以myerrno没有改变

当我们链接完毕之后,可采用指令ldd a.out查看所依赖的动态库,这里却并没有mymath.c

image-20231115204125246

gcc默认动态链接,我们这里只提供了静态库,所以gcc只能对这个库进行静态链接。

这里动静态库都链接了,这也说明,如果需要gcc可以同时链接多个动静态库

接下来我们将我们的库文件拷贝到系统路径

image-20231115205743400

然后不带上IL这些选项,编译发现,并没有出现找不到头文件的错误,出现的是链接错误

image-20231115205940209

还是需要链接gcc main.c -lmymath

image-20231115210033429

我们上面的对库进行拷贝,本质上就是对这个三方库进行安装,所谓的下载,就是在系统路径下去掉这个库。

这里第三方库,必须要指明库名称!

当然,这里并不是很建议将自己写的库安装到系统路径,我们也可以采用软连接的方式

sudo ln -s /home/Pyh/linux/study/lib_11_15/test/lib/include /usr/include/myinc
sudo ln -s /home/Pyh/linux/study/lib_11_15/test/lib/mymathlib/libmymath.a /lib64/libmymath.a

image-20231116091609995

image-20231116091822359

这两种方式都可以,但是对于第三方库,我们还是需要安装他们都说明书来进行安装

2. 动态库

不管是形成动态库还是静态库,第一步都是先将源文件生成目标.o文件

image-20231116093631971

采用指令:

gcc -fPIC -c myprint.c
gcc -fPIC -c mylog.c

然后将其打包,ar指令是专门打包静态库的。形成动态库直接采用的是gcc

gcc -shared -o libmymethod.so *.o

生成可执行程序就是将所有的.o文件链接,可是我们的这两个.o里面并没有main函数,都是提供的方法,所以要跟上shared,表示生成共享库(动态库)

image-20231116101050170

这里形成的动态库是有可执行权限的,而静态库是没有的

静态库是提供源代码的,在形成可执行的时候,它的作用就是将需要的内容拷贝过去,并不会加载到内存

对于动态库来说,它要和可执行程序产生关联,当可执行程序运行时,要访问动态库的内容,要跳转到动态库,那么动态库就必须加载到内存当中,所以要有可执行权限

我们可以使用Makefile一次性生成我们的动静态库

dynamic-lib=libmymethod.so
static-lib=libmymath.a.PYONY:all
all:$(dynamic-lib) $(static-lib)$(static-lib):mymath.oar rc $@ $^
mymath.o:mymath.cgcc -c $^$(dynamic-lib):mylog.o myprint.ogcc -shared -o $@ $^
mylog.o:mylog.cgcc -fPIC -c $^
myprint.o:myprint.cgcc -fPIC -c $^.PHONY:clean
clean:rm -rf *.o *.a *.so mylib.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp *.h mylib/includecp *.a mylib/libcp *so mylib/lib

这个单独使用静态库还是和上面一样,就不做演示了。我们来使用动态库看看,方法也是一样

image-20231116111000244

生成可执行程序没有问题,但是运行的时候报错了。

我们先看一下依赖的动态库ldd a.out

image-20231116113227772

发现这里是not found,我们在file a.out看一下,这个程序是使用共享库的

image-20231116113420002

那么问题就是出现在了这个not found

我们这里是动态库,我们只是告诉了编译器,这个库的路径在哪里。可是动态库是要加载到内存的,系统的加载器并不知道它在哪儿。

这也可以想静态库一样,直接安装到系统路径下,这里就不演示了。

  • 方法1:拷贝到默认库路径

  • 方法2:建立软链接

    sudo ln -s /home/Pyh/linux/study/lib_11_15/test/mylib/lib/ /lib64/libmymethod.so
    

    image-20231116164533102

  • 方法3:将自己库所在的路径,添加到系统环境变量LD_LIBRARY_PATH

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/Pyh/linux/study/lib_11_15/test/mylib/lib
    

    image-20231116192936219

    如果重新登录,那么这个配置的环境变量就失效了,要是想长久有效,可以将其添加到系统启动时候的脚本里面~/.bash_profile

    image-20231116213355331

  • 方法4:在目录/etc/ld.so.conf.d里面,加上后缀位.conf的路径文件,然后ldconfing即可(需要root权限)

    image-20231116235237846

    这里不用添加库名字,因为我们这个程序在编译的时候,已经知道了库的名字,所以系统知道链接哪个库

其实在实际情况下,我们用的库都是别人成熟的库,都采用直接安装到系统当中

推荐库ncurses,这个是基于终端的,可提供一些图形化界面的库

3. 动态库的加载

  1. 动态库在程序运行的时候,会被加载到内存当中,而静态库没有;
  2. 创建的动态库被所以的可执行文件动态链接,都要使用,所以动态库也叫共享库。

所以动态库在系统加载之后,会被所有的进程共享。

那这个动态库是怎么加载的呢?

动态库也是文件,文件都是存储在磁盘上。如果我们要执行这个程序需要访问这个库的代码,那么这个库就会加载到内存当中。

而进程访问内存是页表映射的方式,那么这个加载到内存的库,就会映射到页表,然后页表再映射到进程地址空间的共享区里面,这时候代码区要访问这个库,就跳转共享区,拿到要的方法,执行完毕之后再返回代码区。所以在建立映射之后,我们执行的任何代码,都是在进程地址空间中执行的。

一个共享库可以给多个进程使用,而一个进程也可以使用多个共享库,这就说明在系统当中,一定会有多个动态库,操作系统要将这些库管理起来,也是六个字先描述,再组织。所以这个共享库有没有加载到内存当中,操作系统是十分清楚的。

这里还有个问题,动态库中,可能会存在全局变量,例如errno这样的,如果我们的进程将其修改了,会不会影响其他的进程呢?

这肯定是不会的,如果这个进程要修改这个全局变量,就需要对这个变量进行写入,写入的过程会发生写时拷贝。这也是进程为什么具有独立性的一个原因!

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

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

相关文章

Jmeter- Beanshell语法和常用内置对象(网络整理)

在利用jmeter进行接口测试或者性能测试的时候&#xff0c;我们需要处理一些复杂的请求&#xff0c;此时就需要利用beanshell脚本了&#xff0c;BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法&#xff0c;所以它和java是可以无缝衔接的。beans…

<MySQL> 什么是数据库索引?数据库索引的底层结构是什么?

目录 一、什么是数据库索引? 1.1 索引的概念 1.2 索引的特点 1.3 索引的适用场景 1.4 索引的使用 1.4.1 创建索引 1.4.2 查看索引 1.4.3 删除索引 二、数据库索引的底层结构是什么&#xff1f; 2.1 数据库中的 B树 长啥样&#xff1f; 2.2 B树为什么适合做数据库索…

B树与B+树

B树 B树&#xff0c;又称多路平衡查找树&#xff0c;B树中所有结点的孩子个数的最大值称为B树的阶&#xff0c;通常用m表示。一颗m阶B树或为空树&#xff0c;或为满足如下特征的m叉树。 树中每个结点至多有m棵子树&#xff0c;即至多含有m-1个关键字若根结点不是终端结点&…

从0到0.01入门 Webpack| 002.精选 Webpack面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

力扣刷题篇之数与位3

系列文章目录 目录 系列文章目录 前言 数学问题 总结 前言 本系列是个人力扣刷题汇总&#xff0c;本文是数与位。刷题顺序按照[力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 - 力扣&#xff08;LeetCode&#xff09; 数学问题 204. 计数质数 - 力扣&#xff08;Le…

【开源】基于JAVA的大学兼职教师管理系统

项目编号&#xff1a; S 004 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S004&#xff0c;文末获取源码。} 项目编号&#xff1a;S004&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 学生教师管…

APIcloud 【现已更名 用友开发中心】 iOS发版 应用程序请求用户同意访问相机和照片,但没有在目的字符串中充分说明相机和照片的使用。

iOS 审核时 提示 首次安装软件 获取相机 相册 提示信息 怎么修改 我们注意到你的应用程序请求用户同意访问相机和照片&#xff0c;但没有在目的字符串中充分说明相机和照片的使用。 为了解决这个问题&#xff0c;修改应用信息中的目的字符串是合适的。相机和照片的Plist文件&a…

Skywalking流程分析_9(JDK类库中增强流程)

前言 之前的文章详细介绍了关于非JDK类库的静态方法、构造方法、实例方法的增强拦截流程&#xff0c;本文会详细分析JDK类库中的类是如何被增强拦截的 回到最开始的SkyWalkingAgent#premain try {/** 里面有个重点逻辑 把一些类注入到Boostrap类加载器中 为了解决Bootstrap类…

python科研绘图:P-P图与Q-Q图

目录 什么是P-P图与Q-Q图 分位数 百分位数 Q-Q图步骤与原理 Shapiro-Wilk检验 绘制Q-Q图 绘制P-P图 什么是P-P图与Q-Q图 P-P图和Q-Q图都是用于检验样本的概率分布是否服从某种理论分布。 P-P图的原理是检验实际累积概率分布与理论累积概率分布是否吻合。若吻合&#xf…

SpringBoot整合Quartz示例

数据表 加不加无所谓,如果需要重启服务器后重新执行所有JOB就把sql加上 如果不加表 将application.properties中的quartz数据库配置去掉 自己执行自己的逻辑来就好,大不了每次启动之后重新加载自己的逻辑 链接&#xff1a;https://pan.baidu.com/s/1KqOPYMfI4eHcEMxt5Bmt…

2023年05月 Python(六级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 明明每天坚持背英语单词,他建立了英语单词错题本文件“mistakes.txt”,将每天记错的单词增加到该文件中,下列打开文件的语句最合适的是?( ) A: f = open(“mistakes.txt”) B: …

yolov5模型代码怎么修改

yaml配置文件 深度乘积因子 宽度乘积因子 所有版本只有这两个参数的不同&#xff0c;s m l x逐渐加宽加深 各种类型层参数对照 backbone里的各层&#xff0c;在这里解析&#xff0c;只需要改.yaml里的各层参数就能控制网络结构 修改网络结构 第一步&#xff1a;把新加的模块…

家庭网络中的组网方式

家庭网络中&#xff0c;目前也衍生出了比较多的组网方式&#xff0c;也不是只有Easymesh&#xff0c;我们还是要辩证的去看&#xff0c;没有绝对的好和坏&#xff0c;需求不同&#xff0c;取舍不同。 这里博主简单的介绍几种组网方式&#xff0c;上图也比较直观 1.wds wds是…

Windows系统中搭建docker (ubuntu,Docker-desktop)

一、docker安装前的准备工作 1. 开启CPU虚拟化&#xff0c;新电脑该默认是开启的&#xff0c;如果没开启可以根据自己电脑型号品牌搜索如克开启CPU虚拟化。当开启成功后可在设备管理器中看到。 2.开通Hyper-V 通过 Windows 控制面板 --> 程序和功能 -->启用或关闭…

Windows 11 设置 wsl-ubuntu 使用桥接网络

Windows 11 设置 wsl-ubuntu 使用桥接网络 0. 背景1. Windows 11 下启用 Hyper-V2. 使用 Hyper-V 虚拟交换机管理器创建虚拟网络3. 创建 .wslconfig 文件4. 配置 wsl.conf 文件5. 配置 wsl-network.conf 文件6. 创建 00-wsl2.yaml7. 安装 net-tools 和 openssh-server 0. 背景 …

Day48 力扣动态规划 : 647. 回文子串 |516.最长回文子序列 |动态规划总结篇

Day48 力扣动态规划 : 647. 回文子串 &#xff5c;516.最长回文子序列 &#xff5c;动态规划总结篇 647. 回文子串第一印象看完题解的思路dp递推公式初始化递归顺序 实现中的困难感悟代码 516.最长回文子序列第一印象我的尝试遇到的问题 看完题解的思路dp递推公式初始化 实现中…

搜维尔科技:业内普遍选择Varjo头显作为医疗VR/AR/XR解决方案

Varjo 的人眼分辨率混合现实和虚拟现实头显将医疗专业人员的注意力和情感投入提升到更高水平。借助逼真的 XR/VR&#xff0c;医疗和保健人员可以为最具挑战性的现实场景做好准备&#xff01; 在虚拟、增强和混合现实中进行最高水平的训练和表现 以逼真的 3D 方式可视化医疗数据…

基于Element-Plus动态配置Menu 菜单栏

文章目录 前言先看效果可兼容多级菜单栏&#xff08;顺便配置多少级&#xff09; 一、新建组件二、使用步骤总结如有启发&#xff0c;可点赞收藏哟~ 前言 菜单栏配置化 图标配置化参考vite动态配置svg图标及其他方式集合 先看效果 可兼容多级菜单栏&#xff08;顺便配置多少级…

系列一、请谈谈你对JVM的理解?Java8的虚拟机有什么更新?

一、请谈谈你对JVM的理解&#xff1f;Java8的虚拟机有什么更新&#xff1f; JVM是Java虚拟机的意思。它是建立在操作系统之上的&#xff0c;由类加载器子系统、本地方法栈、Java栈、程序计数器、方法区、堆、本地方法库、本地方法接口、执行引擎组成。 &#xff08;1&#xff0…

istio安装文档

1、重装命令 istioctl manifest generate --set profiledemo | kubectl delete --ignore-not-foundtrue -f - 2、下载 参考&#xff1a;02、istio部署到k8s中 - 简书 (jianshu.com) 参考 Istio / 入门 curl -L https://istio.io/downloadIstio | ISTIO_VERSION1.20.0 TAR…