【Linux】静态库与动态库制作及运行原理
Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。
本篇导航
- 0. 静态库与动态库
- 1. 制作与使用静态库
- 2. 制作与使用动态库
- 3. 动态库是如何被加载到内存?
- 3.1程序地址空间

0. 静态库与动态库
先来总体描述下静态库与动态库的区别.
静态库是将头文件总体复制到可执行文件当中。动态库是在可执行程序运行时进行了动态链接(所需要某个实现方法就去内存中查找).
所以静态链接所形成的可执行文件可以在没有相关配置的设备上运行,而动态链接的可执行程序对设备环境要求较高.
通常情况下,我们将自己的代码提供给别人使用时,往往只会提供: 头文件与源码打包成的库.这个库可以是动态链接也可以是静态链接.
- 总结:动静态库都为将形成的二进制码进行链接的过程,二者区别仅为链接方式不同
1. 制作与使用静态库
接下来介绍如何制作一个自己的静态链接库.
我们先正常进行一段编码.分别编写头文件.h与方法.c
// .h编写
#pragma once
int add(int x,int y);
// .c编写
extern int myerrno;int add(int x,int y)
{return x+y;
}
我们先使用如下指令对.c进行编译
gcc -c myadd.c
# 该指令会自动生成.c同名的.o文件
接下里就是对myadd.o进行链接的过程
我们使用ar工具带上rc选项来进行链接,具体指令如下
静态链接库的文件名格式为 libxxx.a
ar -rc libmyadd.a myadd.o
此时就编译完成了我们所需要的静态库.
现在我们试试写一段代码去引用下我们的方法.
#include "myadd.h"
#include<stdio.h>
int main()
{printf("%d\n",add(1,2));return 0;
}
接下来我们试着用gcc进行编译运行看看
gcc -o test test.c
显示其不认识我们的add函数,但是我们不是将头文件包含了嘛?
这是因为gcc编译时会去特定的路径下查找头文件与库文件信息.
该目录结构一般如下
在lib/include路径下存放我们自定义的头文件 在lib/myaddlib存放我们打包生成好的库文件.
之后,手动指定gcc去哪里寻找对应的链接文件
gcc -o test test.c -I lib/include -L lib/myaddlib -lmyadd
其中 -I表示头文件在哪个路径下 -L表示链接文件在哪个路径下 -l表示具体是哪个链接文件的路径(此时要去掉前缀lib去掉后缀.a)
为什么头文件不需要指定名称了呢?因为我们在代码中已经手动include "头文件"了
那么为什么我们平常使用时没有这么麻烦呢?
因为系统在安装库时,把所有需要的文件放在了指定目录下,gcc编译时会自己去该目录进行寻找,我们仅需要制定形成的链接文件即可
头文件存储在 /usr/include中 形成的链接文件放在/lib64下
我们试试将我们的东西软连接到对应目录下
sudo ln -s $(pwd)/lib/include /usr/include/lib
sudo ln -s $(pwd)/lib/myaddlib/libmyadd.c /lib64/libmyadd.c
此时我们直接带上-l选项即可完成编译
gcc -o test test.c -lmyadd
这也为安装静态库的方法,我们可以通过复制/软链接到对应的目录
在编译完成后该文件即可独立运行,此时将编译时所依赖文件全部删除也不影响该程序运行
makefile:
lib=libmyadd.a$(lib):myadd.oar -rc $@ $^
myadd.o:myadd.cgcc -c $^ .PHONY:clean
clean:rm -rf *.o lib *.a test *.a*.PHONY:output
output:mkdir -p ./lib/includemkdir -p ./lib/myaddlib/cp *h ./lib/includecp *a ./lib/myaddlib
2. 制作与使用动态库
先来介绍一个指令: ldd + 可执行文件
可以列出当前文件运行时所需的动态库目录,例如我们刚刚使用的test
为了方便介绍,我们将多个方法.c文件打包成一个动态库文件
// myPrintf.h
#pragma once
#include <stdio.h>
void Printf();
// myLog.h
#pragma once
#include <stdio.h>
void Log();
// myPrintf.c
void Printf()
{printf("hello myprintf\n");
}
// myLog.c
void Log()
{printf("hello mylog\n");
}
将其进行编译成二进制文件
gcc -fpic -c myPrintf.c myLog.c
fpic为与位置无关码
将其进行链接
gcc -shared -o libmyfunc.so myPrintf.o myLog.o
动态库的后缀为so,前缀为lib
此时一个名为 libmyfunc.so的可执行文件就被编译生成了.(至于为什么是可执行的我们之后再说)
为了规范 我们将其放进如下目录
同样编写一段代码尝试使用
// test.c
#include "./lib/include/myLog.h"
#include "./lib/include/myPrintf.h"
int main()
{Printf();Log();return 0;
}
编译指令与静态库相似
gcc -o mytest test.c -I ./lib/include -L ./lib/lib -lmyfunc
但是,此时我们直接运行会发现.
原因:动态库并不会将自己的库文件放进可执行程序,其运行时动态在内存中进行查找.而我们上面仅告诉了编译器我们的动态库在哪,而加载器并不知道,所以找不到
- 方法也是将自己的动态库文件拷贝/软连接到/lib下
- 一个方法是修改/etc/ld.so.conf.d下的文件内容
在该目录下创建一个.conf结尾的文件,将动态库所在的文件目录路径填入即可
sudo ldconfig
- 还有一个方法是导入环境遍历 LD_LIBRARY_PATH后面带上上文的路径即可
3. 动态库是如何被加载到内存?
3.1程序地址空间
在文件被编译编程成可执行程序时,会有一套自己的内部地址.与PCB私有的栈帧模型类似
将代码放在了代码区,只读变量放在了只读变量区等…
他私有的地址,当其放入内存时,就有物理地址自动与其一一对应
当cpu访问对应代码时,会从内存中将其放入页表上,此时已经有物理地址与虚拟地址的映射.直接放入即可.
动态库与普通文件无异,也会被加载到内存中。当文件需要调用时,将其映射到PCB的共享区.
多个PCB可以映射同一个动态库文件.errno用到的技术为写时拷贝
函数内部调用会跳转到函数的虚拟地址.
若该函数为动态库的函数,则该函数存储的是从共享区开头到目标动态库函数的偏移量.
这就是动态库编译选项中与位置无关码FPIC的含义
当cpu访问对应代码时,会从内存中将其放入页表上,此时已经有物理地址与虚拟地址的映射.直接放入即可.
动态库与普通文件无异,也会被加载到内存中。当文件需要调用时,将其映射到PCB的共享区.
多个PCB可以映射同一个动态库文件.errno用到的技术为写时拷贝
函数内部调用会跳转到函数的虚拟地址.
若该函数为动态库的函数,则该函数存储的是从共享区开头到目标动态库函数的偏移量.
这就是动态库编译选项中与位置无关码FPIC的含义
相关文章:

【Linux】静态库与动态库制作及运行原理
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法…感兴趣就关注我吧!你定不会失望。 本篇导航 0. 静态库与动态库1. 制作与使用静态库2. 制作与使用动态库3. 动态库是如何被加载到内存?3.1程序地址空间 0. 静态库…...

工具站推荐
自己搭了一个文本工具站 TextTool,包含了常用的文本功能。 我自己比较常用 行转列、列转行、下划线替换的功能。 欢迎各位大佬提意见和建议...

【JS】toFixed()无法精准保留小数的解决方案
情景复现: 发现用 toFiexd() 四舍五入保留小数有时不是很精确,接下来用 a 8.0345,b8.045,举例如下: var a 8.035; console.log(a.toFixed(2)) // 8.04 var b 8.045; console.log(b.toFixed(2)) // 8.04 不难看出…...

vue3版本学习
1,响应式ref或者reactive const aa ref(hello) const bb reactive({ aa: hello, ss: workd }) 2,计算属性 响应式属性经过计算得到的值(ref),放到模板中,只会随着响应式author.books属性变化而变化 const autor …...

【WPF.NET开发】创建简单WPF应用
本文内容 先决条件什么是 WPF?配置 IDE创建项目设计用户界面 (UI)调试并测试应用程序 通过本文你将熟悉在使用 Visual Studio 开发应用程序时可使用的许多工具、对话框和设计器。 你将创建“Hello, World”应用程序、设计 UI、添加代码并调试错误。在此期间&#…...

视频智能分析国标GB28181云平台EasyCVR加密机授权异常是什么原因?
国标GB28181视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等。 近期有用户选择使用加密机进行EasyCVR授…...

Mysql安全之基础合规配置
一、背景 某次某平台进行安全性符合型评估时,列出了数据库相关安全选项,本文特对此记录,以供备忘参考。 二、安全配置 2.1、数据库系统登录时的用户进行身份标识和鉴别; 1)对登录Mysql系统用户的密码复杂度是否有要…...

前后端分离项目跨域请求
一、前端vue项目 在项目中创建request.js文件,添加以下内容 import axios from "axios"; const api axios.create({ //这里配置的是后端服务提供的接口baseURL: "http://localhost:8080/web-demo",timeout: 1000} ); export default api; …...

OpenEuler系统桌面终端设置字体
初始界面 终端的字体间距过大,阅读起来不方便。 调整终端字体 点击菜单,选择“配置文件首选项” 未命名 ---- 文本---- 勾选 自定义字体 ---- 选择 "DejaVu LGC Sans Mono"字体 你也可以根据自己的喜好,选择其他字体。 修改好了…...

repo常用命令解析(持续更新)
1 同步 1.1 将本地仓库更新到最新状态。它会从远程服务器下载最新的代码,并将本地仓库与之同步。如果本地仓库中已经存在某个项目,repo sync会自动检测本地仓库中该项目的版本,并将其更新到最新状态。 类似于git fetch和git merge命令组合使…...

关于小红书商单变现的一些答疑
AI小红书商单训练营也过去1个月了,今天给大家汇总几个常遇到的问题,希望对大家在运营过程中有所帮助。 1.账号封面是否要统一模版? 为了让账号主页呈现整洁美观的效果,建议统一封面设计,视频开头可以设置一个固定画面…...

使用 Kubernetes Agent Server 实现 GitOps
目录 温习 GitOps 极狐GitLab Kubernetes Agent 极狐GitLab GitOps workflow 极狐GitLab KAS 的配置 创建极狐GitLab agent 创建 agent token Kubernetes 上安装 agent(agentk) 极狐GitLab GitOps workflow 实践 写在最后 温习 GitOps GitOps …...

Day12 qt QMianWindow,资源文件,对话框,布局方式,常用ui控件
QMianWindow 概述 QMainWindow 是一个为用户提供主窗口程序的类,包含一个菜单栏( menu bar )、多 个工具栏 (tool bars) 、多个铆接部件 (dock widgets) 、一个状态栏 (status bar) 及 一个中心部件 (central widget) 许多应用程序的基础…...

Python实现广义线性回归模型(statsmodels GLM算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 广义线性模型(Generalized Linear Model,简称GLM)是一种广泛应用于回归分析和分类问题的统…...

GNSEC 2022年第8届全球下一代软件工程线上峰会-核心PPT资料下载
一、峰会简介 新一代软件工程是指利用新的理论、方法和技术,在软件开发、部署、运维等过程中,实现软件的可控、可预测、可维护的软件生产方式。它涵盖了多个领域,如软件开发、测试、部署、运维等,旨在提高软件生产效率和质量。 …...

nVisual能为数据中心解决什么问题?
nVisual通过可视化的管理方式,使数据中心管理者能够有效且高效地管理数据中心的资产、线缆、容量、变更;使数据中心管理者能够获得如下问题的答案,以便能够快速做出更好、更明智的决策: 1.资产管理 我们有什么&#x…...

Android--Jetpack--Databinding详解
不经一番寒彻骨,怎得梅花扑鼻香 一,定义 DataBinding, 又名数据绑定,是Android开发中非常重要的基础技术,它可以将UI组件和数据模型连接起来,使得在数据模型发生变化时,UI组件自动更新。是 MVVM 模式在 An…...

Node.js入门指南(完结)
目录 接口 介绍 RESTful json-server 接口测试工具 会话控制 介绍 cookie session token 上一篇文章我们介绍了MongoDB,这一篇文章是Node.js入门指南的最后一篇啦!主要介绍接口以及会话控制。 接口 介绍 接口是前后端通信的桥梁 ࿰…...

MySQL和Java通用加密解密方式
加密方式使用 AES 加密,再转成 Base64。 SQL -- 加密 update your_table set your_columnto_base64(aes_encrypt(your_column, "password"));-- 解密 select aes_decrypt(from_base64(your_column) ,"password") from your_table; 使用原生 …...

若依前端APP版使用教程
1 增加页面流程 新增Page>新增API>新增组件>新增样式>新增路径(page.json) {"path": "pages/mes/pro/feedback/index","style": {"navigationBarTitleText": "工单报工"}} <template><view class&quo…...

2023 年工程师不可错过的 AI 主要发展趋势
从对未来的好奇到关键的企业工具,人工智能的发展证明了它对工程师的价值。不久前,Gartner 预测,采用人工智能工程实践来构建和管理自适应人工智能系统的企业,在实施人工智能模型方面的表现将优于同行至少 25%,这为各组…...

记录 | 安装地平线工具链install_ai_toolchain.sh出现cython版本问题报错解决
安装地平线工具链 install_ai_toolchain.sh: cd ddk/package/host/ai_toolchain bash install_ai_toolchain.sh出现报错: Requirement already satisfied: packaging>20.0 in /root/.local/lib/python3.8/site-packages (from matplotlib>2.1.0-…...

Java8流操作
Java8流操作 1. 双层Map一层List 1. 双层Map一层List 代码片 // 开始分组Map<String, Map<Object, List<ProjectGeographyVO>>> collect4 vos.stream()// 注释了下行没用市级项目,只有区// .filter(data -> String.valueOf(data.getCode()).length() …...

vue-socket.io以及原生websocket的使用
vue3使用socket.io 1、安装 npm install vue-socket.io2、创建socket.js文件 export const registerSockets (sockets, proxy) > {sockets &&Object.keys(sockets).forEach((t) > {// console.log(t);// "subscribe" ! t &&// "un…...

谷歌推出功能最强大的大语言模型Gemini;大规模语言模型:从理论到实践
🦉 AI新闻 🚀 谷歌推出功能最强大的大语言模型Gemini 摘要:谷歌正式推出其迄今为止功能最强大、最通用的大语言模型Gemini。Gemini在许多测试中表现出了最先进的性能,在大部分基准测试中击败了OpenAI的GPT-4。谷歌发布了三种不同…...

Android studio 工程的 module 依赖关系图绘制 、 Android Module 依赖关系的可视化实现
整体步骤: 1、利用gradle脚本生成dot; 2、利用graphviz将dot可视化转为图片 利用gradle脚本生成dot 下载projectDependencyGraph.gradle脚本 下载 projectDependencyGraph.gradle ,放在项目根目录, 源码如下: t…...

Qt之QGraphicsView —— 笔记1.2:将QGraphicsView放置主窗口上,绘制简单图元(附完整源码)
效果 相关类介绍 QGraphicsView类提供了一个小部件,用于显示QGraphicsScene的内容。QGraphicsView在可滚动视口中可视化。QGraphicsView将滚动其视口,以确保该点在视图中居中。 QGraphicsScene类 提供了一个用于管理大量二维图形项的场景。请注意,QGraphicsScene没有自己的视…...

linux的权限管理
在Linux系统中,文件和目录的权限管理是通过用户、组以及其他用户对文件和目录的读(r)、写(w)和执行(x)权限来实现的。以下是有关Linux权限管理的详细解释: 文件和目录权限࿱…...

什么是 performance_schema ?
MySQL的performance_schema是运行在较低级别的用于监控MySQL Server运行过程中的资源消耗、资源等待等情况的一个功能特性,它具有以下特点。 performance_schema提供了一种在数据库运行时实时检查Server内部执行情况的方法。performance_schema数据库中的表使用per…...

软件多开助手的创新使用:在同一设备上玩转多个游戏
软件多开助手:在同一设备上玩转多个游戏的创新使用 随着科技的不断发展,手机和电脑已经成为我们生活中必不可少的工具。众多游戏爱好者也越来越追求在同一设备上同时体验多个游戏的乐趣。而软件多开助手的出现为这一需求提供了创新的解决方案。 传统上…...