当前位置: 首页 > news >正文

【Linux】静态库与动态库制作及运行原理

img

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

image-20231206205341040

显示其不认识我们的add函数,但是我们不是将头文件包含了嘛?

这是因为gcc编译时会去特定的路径下查找头文件与库文件信息.

该目录结构一般如下

image-20231206205457112

在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

image-20231206210942172

sudo ln -s $(pwd)/lib/myaddlib/libmyadd.c /lib64/libmyadd.c

image-20231206211022363

此时我们直接带上-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

image-20231206211703294

为了方便介绍,我们将多个方法.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的可执行文件就被编译生成了.(至于为什么是可执行的我们之后再说)

为了规范 我们将其放进如下目录

image-20231206213840507

同样编写一段代码尝试使用

// 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

但是,此时我们直接运行会发现.

image-20231206214323845

原因:动态库并不会将自己的库文件放进可执行程序,其运行时动态在内存中进行查找.而我们上面仅告诉了编译器我们的动态库在哪,而加载器并不知道,所以找不到

image-20231206214456342

  • 方法也是将自己的动态库文件拷贝/软连接到/lib下

image-20231206224245708

  • 一个方法是修改/etc/ld.so.conf.d下的文件内容

在该目录下创建一个.conf结尾的文件,将动态库所在的文件目录路径填入即可image-20231206224820323

sudo ldconfig
  • 还有一个方法是导入环境遍历 LD_LIBRARY_PATH后面带上上文的路径即可

3. 动态库是如何被加载到内存?

3.1程序地址空间

在文件被编译编程成可执行程序时,会有一套自己的内部地址.与PCB私有的栈帧模型类似

将代码放在了代码区,只读变量放在了只读变量区等…

他私有的地址,当其放入内存时,就有物理地址自动与其一一对应

image-20231206225650231

当cpu访问对应代码时,会从内存中将其放入页表上,此时已经有物理地址与虚拟地址的映射.直接放入即可.

动态库与普通文件无异,也会被加载到内存中。当文件需要调用时,将其映射到PCB的共享区.

多个PCB可以映射同一个动态库文件.errno用到的技术为写时拷贝

函数内部调用会跳转到函数的虚拟地址.

若该函数为动态库的函数,则该函数存储的是从共享区开头到目标动态库函数的偏移量.

这就是动态库编译选项中与位置无关码FPIC的含义

当cpu访问对应代码时,会从内存中将其放入页表上,此时已经有物理地址与虚拟地址的映射.直接放入即可.

动态库与普通文件无异,也会被加载到内存中。当文件需要调用时,将其映射到PCB的共享区.

多个PCB可以映射同一个动态库文件.errno用到的技术为写时拷贝

函数内部调用会跳转到函数的虚拟地址.

若该函数为动态库的函数,则该函数存储的是从共享区开头到目标动态库函数的偏移量.

这就是动态库编译选项中与位置无关码FPIC的含义
image-20230905164632777

相关文章:

【Linux】静态库与动态库制作及运行原理

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

工具站推荐

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

【JS】toFixed()无法精准保留小数的解决方案

情景复现&#xff1a; 发现用 toFiexd() 四舍五入保留小数有时不是很精确&#xff0c;接下来用 a 8.0345&#xff0c;b8.045&#xff0c;举例如下&#xff1a; var a 8.035; console.log(a.toFixed(2)) // 8.04 var b 8.045; console.log(b.toFixed(2)) // 8.04 不难看出…...

vue3版本学习

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

【WPF.NET开发】创建简单WPF应用

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

视频智能分析国标GB28181云平台EasyCVR加密机授权异常是什么原因?

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

Mysql安全之基础合规配置

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

前后端分离项目跨域请求

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

OpenEuler系统桌面终端设置字体

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

repo常用命令解析(持续更新)

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

关于小红书商单变现的一些答疑

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

使用 Kubernetes Agent Server 实现 GitOps

目录 温习 GitOps 极狐GitLab Kubernetes Agent 极狐GitLab GitOps workflow 极狐GitLab KAS 的配置 创建极狐GitLab agent 创建 agent token Kubernetes 上安装 agent&#xff08;agentk&#xff09; 极狐GitLab GitOps workflow 实践 写在最后 温习 GitOps GitOps …...

Day12 qt QMianWindow,资源文件,对话框,布局方式,常用ui控件

QMianWindow 概述 QMainWindow 是一个为用户提供主窗口程序的类&#xff0c;包含一个菜单栏&#xff08; menu bar &#xff09;、多 个工具栏 (tool bars) 、多个铆接部件 (dock widgets) 、一个状态栏 (status bar) 及 一个中心部件 (central widget) 许多应用程序的基础…...

Python实现广义线性回归模型(statsmodels GLM算法)项目实战

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

GNSEC 2022年第8届全球下一代软件工程线上峰会-核心PPT资料下载

一、峰会简介 新一代软件工程是指利用新的理论、方法和技术&#xff0c;在软件开发、部署、运维等过程中&#xff0c;实现软件的可控、可预测、可维护的软件生产方式。它涵盖了多个领域&#xff0c;如软件开发、测试、部署、运维等&#xff0c;旨在提高软件生产效率和质量。 …...

nVisual能为数据中心解决什么问题?

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

Android--Jetpack--Databinding详解

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

Node.js入门指南(完结)

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

MySQL和Java通用加密解密方式

加密方式使用 AES 加密&#xff0c;再转成 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…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...