【Linux】动态库与静态库,如何打包库,如何使用第三方库

news2024/12/27 13:01:39

文章目录

  • 回顾基础
  • 学会打包自己的库并使用
  • 静态库
    • 打包库
    • 第三方库的使用
  • 动态库
    • 打包库
    • 第三方库的使用
  • 动态库加载以及周边问题


回顾基础

这篇文章主要对动静态库进行进一步的学习,关于动静态库的一些基础知识,请点击这篇文章的链接:【Linux】初识动静态库

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)。
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

1.我们在vs编译器下安装开发环境——本质就是安装编译器软件,安装要开发的语言配套的库和头文件。

2.我们在使用编译器的时候,都会有语法的自动提醒功能,有这个提醒功能的前提是要先包含对应的头文件的,所以语法提醒的本质就是编译器或者编辑器,会自动根据用户输入的内容,不断的在被包含的头文件中进行搜索,自动提醒功能是依赖头文件的。

3.系统已经预装了C/C++的头文件和库文件,头文件提供方法说明,库才提供方法实现,头和库是有对应关系的,是要组合在一起使用的。

4.头文件是在预处理的阶段就引入的,链接的本质实际是在链接库。

学会打包自己的库并使用

静态库

打包库

这里我们用一个简单的加减函数来示范,我们先创建以下几个文件,并在mysub,myadd文件中实现对应的功能。(简单的加减函数这里就不赘述了)
在这里插入图片描述

当别入需要使用我们实现的代码功能时,我们不可能把myadd.c,mysub.c源代码直接交出去,因为这就暴露了我们代码的实现细节,所以我们往往将.c .h文件打包成一个库(二进制文件),再给别人。

所以我们这里又创建了一个目录otherPerson代表需要用我们打包的库的其他人。

开始演示:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原因:当我们有了一个库,接下来,要将库引入我们的项目,必须让编译器找到头文件+库文件。
在这里插入图片描述
看!现在“别人”通过库文件和头文件就可以成功运行程序了。

步骤:

  1. 先准备好.h和.c文件,然后用gcc-c选项生成.o目标文件;
  2. 命令ar -rc libmymath.a *.o生成静态库,ar是gnu归档工具,rc表示(replace and create);
  3. 查看静态库的目录列表:ar -tv libmymath.a,t:列出静态库中的文件,v:详细信息;
  4. 运行程序命令:gcc -o mytest main.c -L. -lmymath,-L:指定库路径,-l:指定库名
  5. 测试目标文件生成后,静态库删掉,程序照样可以运行。

但实际上一般是打包头文件和库文件给其他人的:
在这里插入图片描述
在这里插入图片描述

第三方库的使用

1.需要指定的头文件和库文件;
2. 如果没有默认安装到系统gcc,g++默认的搜索路径下,用户必须指明对应的选项,告知编译器头文件在哪里,库文件在哪里,库文件具体是谁。
3. 将我们下载下来的库和头文件,拷贝到系统默认路径下——这个行为就是在Linux下安装库。对任何软件而言,安装和卸载的本质就是拷贝到系统的特定路径。

在这里插入图片描述
4. 如果我们按安装的是第三方的(1,2语言,操作系统接口)库,我们要正常使用,即便是已经全部安装到了系统中,gcc/g++必须用-l指明具体库的名称。
5. 无论是从网络中直接下好的库,或者源代码(可能会提供内置编译方法)——必须有make install安装的命令,实际上就是拷贝安装到系统中,所以我们安装大部分命令,库等等,都是需要sudo或者超级用户操作(因为需要访问系统)。

将第三方库安装到系统中:(还是以上述为例子)

a.提取权限将我们include目录下的所有头文件拷贝到系统头文件/usr/include/中:
sudo cp -rf include/* /usr/include/

b.提取权限将我们lib目录下的静态库拷贝到系统的库/lib64中:
sudo cp lib/* /lib64

c.这时就算我们删除了lib和include目录,只有main.c文件,也能成功生成可执行程序,正确编译:
gcc -o mytest main.c -lmymath

云服务器一般都只会提供动态库,下面是安装静态库的命令:

sudo yum install -y glibc-static
sudo yum install -y libstdc++-static

动态库

打包库

还是以上面的加减函数为例:
在这里插入图片描述
编译生成.o目标文件:
fPIC:产生位置无关码(position independent code)
在这里插入图片描述
进行打包,动态库的打包就不是用ar了,而是还是用gcc,用法如下:
shared: 表示生成共享库格式
.o文件打包成动态库:
在这里插入图片描述
还是一样的准备两个自己的目录:include和lib,分别装填自己的头文件和动态库。
在这里插入图片描述
将头文件include和lib库文件打包:
在这里插入图片描述

第三方库的使用

将mylib中我们已创建好的包mymath.tgz传给“其他人”,本质是拷贝到指定目录下的一个过程。
在这里插入图片描述

在这里插入图片描述
报的错是找不到动态库,但是我们已经采用上面讲到过的方法,告诉了编译器头文件的位置-I和库的位置-L,还有文件名-l,但是竟然没有成功!为什么呢?

那是因为,运行的时候.so文件并没有在系统的默认路径下,所以操作系统依旧找不到,静态库能找到的原因是,静态库的链接原则是将用户使用的二进制代码拷贝到了目标可执行程序中,但是动态库的链接原则不是这样的。

那么运行时,OS是如何查找动态库?方法如下:

方法一:配置环境变量

环境变量:LD_LIBRARY_PATH(临时方案,因为环境变量只在当前会话有效,退出了就没了)

在这里插入图片描述

echo $LD_LIBRARY_PATH //查看环境变量

在这里插入图片描述

方法二:软链接方案

我们在/lib64下建立了一个软链接,指向libmymath.so目标文件的所在路径。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法三:配置文件方案

1.所要配置的文件名称:/etc/ld.so.conf.d/
2.获取权限在该配置文件下创建一个你的文件,如:sudo touch /etc/ld.so.conf.d/nan_test.conf
3.查看是否创建成功:ls /etc/ld.so.conf.d/
4.查看所需第三方动态库所在路径,以上述例子为例,lib动态库的路径是:
/home/nan/linux-learning/基础IO/动态库/otherPerson/lib
5.获取权限vim打开你刚刚在配置文件下创建的文件:sudo vim /etc/ld.so.conf.d/nan_test.conf将你刚刚获得的动态库路径添加进去,并保存。
6.ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新:sudo ldconfig
7.查看动态库是否添加成功:ldd mytest(可执行程序)
8.最后执行程序,over!!!

动态库加载以及周边问题

静态链接的加载:静态链接形成的可执行程序,本身就有静态库中对应方法的实现,但是非常占用资源!(可执行程序变大加载占用内存,下载周期变长,占用网络资源)

动态链接的加载:将可执行程序中的外部符号,替换成为库中的具体地址。只要我们把库加载到内存,映射到进程的虚拟地址空间之后,我们的代码执行库中的方法,在自己的地址空间内进行函数跳转即可。

库中地址的理解

动态库面临一个问题:不同的进程,运行程度不同,需要使用的第三方库是不同的,每一个进程的共享空间(栈和堆之间有一块共享区)中空闲位置是不确定的!那么动态库和静态库加载的地址是怎么处理的呢?

答:由编译器确定,编译器确定地址分为两种形式:
1.根据当前PC+偏移量确定地址(动态库采用)
2.直接用链接地址(通过链接脚本指定)(静态库采用)

区别就是:代码运行的时候,是否和所处内存地址有关。
位置有关码要求运行是代码必须在特定位置;
位置无关码则没有要求,动态库中的所有地址,都是相对于当前PC值的偏移量,默认地址从0地址开始。动态库,在进程的地址空间中,随便加载,与我们加载到地址空间的什么位置,就毫无关系了,动态库中地址,都是偏移量。

这也就是为什么,上面我们在制作动态库的时候,要加上-fPIC选项:
在这里插入图片描述
位置无关码和位置有关码可以用下面一个生活的例子感性理解一下:
在这里插入图片描述
1.我在这条路的60米处左右——绝对编址
2.我在这条路的一棵大树左边,大约距离20米——相对编址

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

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

相关文章

【Docker】如何实现Docker 命令自动补全

前言 Docker 命令可以使用 tab 键补全。在命令行输入 Docker 命令时,只需输入前几个字符,然后按 Tab 键即可自动补全为正确的命令或参数。 例如,在命令行输入 docker r,然后按 Tab 键,就会自动补全为 docker run 命令…

YOLOv7训练自定义数据集

使用YOLOv7做对比实验,需要重新部署一下YOLO环境,并将COCO格式数据集转换为YOLO格式 博主的COCO数据集是由WiderPerson数据集转换来的,并且做了一些处理。 环境 Ubuntu18.0 CUDA11.2 NVIDIA T4 项目部署 下载项目: git clone…

SSM-Spring+SpringMVC+MyBatis框架的水果商城网站

项目介绍 主要功能: 前端用户购物端: ①角色信息:用户注册、用户登录、个人中心 ②个人中心:基本信息、我的订单、商品收藏、修改密码 ③首页管理:公告、留言、折扣大促销、热门商品 ④商品详情:收藏、加入…

基于Fragstats做土地利用景观格局分析详细流程

随城市化进程加快,城市经济迅速发展,城市面积不断向外扩展,景观空间组分不断发生变化,主要表现为:生态斑块支离破碎,生物多样性降低,原始的乡村田野景观被现代化建设用地取代;交通网…

数据结构与算法之树结构

目录 为什么要使用树结构树结构基本概念树的种类树的存储与表示常见的一些树的应用场景为什么要使用树结构 线性结构中不论是数组还是链表,他们都存在着诟病;比如查找某个数必须从头开始查,消耗较多的时间。使用树结构,在插入和查找的性能上相对都会比线性结构要好 树结构…

POSTGRESQL NEON - Serverless 式的POSTGRESQL 数据库的独特技能 分支数据

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共…

客户与企业:一场关于体验定义的拉锯战

Guofu 第 98⭐️ 篇原创文章分享 (点击👆🏻上方卡片关注我,加⭐️星标⭐️~) 谈及客户体验的定义,我觉得暂时我的思考并不足以给出如此大框架的概念,本着以此抛砖引玉,和大家分享一下…

从广东电信故障看雪崩

本文几乎与此次故障无关,它只是写本文的缘起。 周五早上发一则朋友圈,呼应一下周四下午广东电信的故障: 我在第一时间(2 点 15 左右)发觉问题,随后我怀疑欠费,马上充值 200 块,未恢复,再次充值…

React diff的原理是什么

一、是什么 跟Vue一致,React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,使我们的页面的构建效率提到了极大的提升 而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处 传统diff算法通过循环递归对节点进行依…

【JavaEE】使Cookie与Session失效-表白墙退出登录操作-Servlet上传文件操作-表白墙注册上传头像+登录显示头像功能

表白墙退出登录操作-表白墙注册上传头像登录显示头像功能 文章目录 【JavaEE】使Cookie与Session失效-表白墙退出登录操作-Servlet上传文件操作-表白墙注册上传头像登录显示头像功能1. Cookie与Session的删除1.1 表白墙页面增加登录出口1.2 点击链接退出登录1.3 测试 2. 上传文…

最新版的配音软件--- tts-vue 软件 下载安装成功过程

目录 本次软件是 Loker 制作,感谢作者的无私奉献。 软件视频效果 软件图片效果 1:电脑版的tts-vue 软件下载链接以及说明: 2:tts-vue 网站在线转换链接: 3:tts-vue 软件 功能简介 截至最新版本&#…

如何根据波特率计算设备每秒传输多少字符

前言 (1)微机原理要进行期末考试了,要准备“预习”了。今天看到关于波特率和字符传输的知识,感觉这个在实际项目中可能会使用到。 (2)因为之前我在学习韦东山老师的课程的时候,他通过波特率计算…

基于SpringBoot+Thymeleaf仓库管理系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 随着信息技术的快速发…

群晖IPv6/ddns-go/域名解析设置内网穿透方案

前言 群晖的内网穿透有很多方案,外网IPv4(这个现在很难搞到了),中间服务器搭建Tunnel隧道,frp等方案(网速慢,流量限制,需另购服务器),第三方服务花生壳等(按量付费,速度问题)。 本篇介绍的是 …

阿里云安装和远程连接mysql8.0数据库

目录 在云服务器安装MySQL8.0(详细版): 安装过程中遇到的两个问题的解决方式 无法获取support-files/mysql.server 的文件状态(stat): 没有那个文件或目录 解决不能进行远程连接,报错Communications link failureThe last pac…

C++算法:排序之四(计数、基数、桶排序)

C算法:排序 排序之一(插入、冒泡、快速排序) 排序之二(归并、希尔、选择排序) 排序之三(堆排序) 排序之四(计数、基数、桶排序) 文章目录 C算法:排序三、非比…

本地gradle在idea中的配置

因为公司在用的gradle构建项目,由于学安卓时候把gradle搞的四不像,所以重新配置了gradle在此记录一下 文章目录 安装gradel官网下载解压init.d里面创建init.gradle文件父目录创建gradleRepository配置环境变量测试是否配置成功 idea配置gradle重新构建项…

深度学习笔记之Seq2seq(二)基于Seq2seq注意力机制的动机

深度学习笔记之Seq2seq——基于Seq2seq注意力机制的动机 引言回顾:基于机器翻译任务的 Seq2seq \text{Seq2seq} Seq2seq网络结构注意力机制的动机循环神经网络作为 Encoder \text{Encoder} Encoder产生 Context \text{Context} Context向量的缺陷注意力机制处理上述…

chatgpt赋能python:Python怎么从列表里随机抽取?

Python怎么从列表里随机抽取? 在编程中,我们常常需要从一个列表里面随机抽取一个元素来进行一些操作,比如说在一个游戏中随机抽取一个怪物来进行战斗。Python提供了一个内置模块——random模块,用于生成随机数。这个模块可以帮助…

(数组) 1207. 独一无二的出现次数 ——【Leetcode每日一题】

❓1207. 独一无二的出现次数 难度:简单 给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。 如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。 示例 1: 输入:arr [1,2,2,1,…