当前位置: 首页 > 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…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.

报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符&#xff0c;最后运行&#xff1a;npm run lint --fix...