Linux:动静态库
1.库是什么,作用是什么
库是写好的,现有的可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存中执行。库有两种:
静态库后缀 .a (在linux下) .lib (在windows下)
动态库后缀 .so (在linux下) .dll (在windows下)
静态库
静态库 (.a):程序在编译链接的时候把库里的代码链接到可执行文件中链接完后,静态库的代码就成为了目标文件的一部分,如果多个程序使用同一个静态库,那么每个程序都会包含一份该库的副本,从而导致程序体积较大。然后程序运行的时候不再需要静态库了。
优点:
独立性高
静态库在编译时直接嵌入到可执行文件中,程序运行时无需依赖外部库文件,减少了部署时的依赖问题。执行效率高
代码在编译时已完全链接,运行时无需加载外部库,启动速度和执行效率通常更快。部署简单
可执行文件是独立的,无需额外分发或配置库文件,适合嵌入式系统或封闭环境。兼容性问题少
无需担心库版本与系统环境不匹配的问题。缺点:
文件体积大
每个可执行文件都包含库代码的副本,占用更多磁盘和内存空间(尤其是多个程序使用同一库时)。更新困难
库的更新需要重新编译整个程序,维护成本高,无法快速修复漏洞。内存冗余
多个程序运行时,相同库代码的多个副本会重复占用内存。
动态库
动态库(.so):程序运行时才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码,在运行前,外部函数的机器码有操作系统从磁盘上的该动态库中赋值到内存中,这个过程叫做动态链接。
动态库可以在多个程序间共享,所以动态链接使可执行文件更小,节省了磁盘空间。操作系统通过虚拟内存机制 允许物理内存中的一份动态库被所有用到该库的进程共用,节省内存和磁盘空间。
优点:
节省资源
多个程序共享同一动态库文件,减少磁盘和内存占用。更新便捷
替换动态库文件即可更新功能或修复漏洞,无需重新编译程序。支持运行时加载
可实现插件机制或延迟加载,灵活扩展程序功能。编译效率高
链接时仅记录引用,编译速度较快(尤其是大型项目)。缺点:
依赖管理复杂
程序运行时需确保系统中存在正确版本的动态库,否则会崩溃(如“DLL地狱”)。性能略低
首次加载库时需要额外开销,可能影响启动速度。兼容性风险
若动态库接口或行为变更,可能导致依赖它的程序异常(需严格版本控制)。部署稍复杂
需确保目标环境已安装所需动态库,或与程序一起分发。
2.动静态库的原理
一个源文件变为一个可执行文件需要四个步骤:
1.预处理:完成头文件展开、去注释、宏替换、条件编译等、最终形成xxx.i文件。
2.编译:完成词法分析、语法分析、语义分析、符号汇总等。检查后将代码翻译成汇编指令,最终形成xxx.s文件
3.汇编:将汇编指令变为二进制指令、最终形成xxx.o文件。
4.链接:将形成的各个xxx.o文件进行链接最终形成可执行程序。
我们将形成的.o文件打包起来。之后只需要链接这个包即可。这个包就是我们常说的库。
动静态库本质上就是一堆.o文件的集合。使用库只需要提供头文件给使用者。在编译程序时,通过链接指定的库来实现对库中功能的调用。
3.动静态库的打包
四个文件分别是:
add.c
#include"add.h"
int add(int x,int y)
{return x+y;
}
add.h
#pragma once int add(int x,int y);
get_m.c
#include"get_m.h"
int get_m(int a,int b)//return a的b次方
{int t=1;while(b){ if(b&1)//是奇数{ t+=a;//} a=a*a;//自身的平方b=b>>1;//} return t;
}
get_m.h
#pragma onceint get_m(int a,int b);
静态库的打包
1.然后将这些.c文件生成.o文件
2.使用ar指令打包成对应的静态库。
使用格式:
ar 选项 库名 打包文件名
关键的两个选项:
-r(replace): 如果静态库文件当中的目标文件有更新,则用新的目标文件替换就得目标文件
-c(create): 建立静态库文件
3.将头文件和生成的静态库组织起来。
把自己的库提供给他人使用时,通常需要给予两个文件夹:
一个文件夹存放头文件集合。即把所有的.h头文件放到一个目录下
一个文件夹存放所有的库文件。即把生成的.a文件存放到一个目录
4.使用静态库
我们使用自己打包的静态库在使用gcc进行编译时要有以下三个选项:
- -I(大写的i):指定头文件搜索路径。
- -L:指定库文件搜索路径
- -l(小写的L):指明文件需要链接库文件路径下的哪一个库(注意,libmath.a 我们只需-lmath即可 不需要加上lib 和 .a)
我们在命令行中指定头文件的搜索路径,库文件的搜索路径以及具体使用哪个库
例如我们要执行main.c,这个.c文件里使用了静态库中的两个函数。
#include<stdio.h>
#include"add.h"
#include"get_m.h" int main()
{int a=2;int b=20;int res=add(a,b);int sum=get_m(a,b);printf("%d\n",res);printf("%d\n",sum);return 0;
}
上面三个选项都可以选的加空格和不加空格。
我们平时使用gcc之所以没带上这个三个选项是因为,我们之前使用的库都默认在系统路径下,编译器能准确识别这些存在于配置文件的路径,如果我们将头文件和库文件拷贝到系统路径 /usr/include/lib.64 下
- sudo cp libmath/include/* /usr/include/
- sudo cp libmath/lib/* /lib.64/
这样只需要带 -l(小写的L) 指明链接库文件下具体哪个库。
但是不推荐这么做可能会污染系统文件。
动态库的打包
1.生成.o文件
区别于静态库需要加上 -fPIC选项(I为大写的i) 。
-fPIC
是一个非常重要的编译选项。它的作用是生成 位置无关代码
位置无关代码是一种特殊的代码,它可以在内存中的任何位置运行,而不需要修改代码本身。
动态库(共享库)会被多个程序共享,并且在运行时加载到内存中。由于无法预知动态库会被加载到内存的哪个位置,因此必须使用位置无关代码来确保动态库的正确运行。
为什么要使用?
动态库在编译时无法确定其加载的内存地址,因此必须使用位置无关代码。
如果不使用
-fPIC
,编译生成的代码可能会包含绝对地址,导致动态库在加载时无法正确运行。使用
-fPIC
可以确保动态库在内存中的任何位置都能正常运行。
2. 打包为动态库,-shared选项
生成动态库不需要ar指令,使用gcc编译加上-shared选项 (shared意为共享)。
3.将头文件和生成的动态库组织起来
将自己的库提供给他人使用时,与静态库一样通常给予两个文件:
将两个头文件放到一个目录 includeso中
生成的动态库文件libmath.so放到libso目录中
4. 动态库的使用
与静态库一样使用gcc编译带上三个选项
- -I(大写的i):指定头文件搜索路径。
- -L:指定库文件搜索路径
- -l(小写的L):指明文件需要链接库文件路径下的哪一个库(注意,libmath.a 我们只需-lmath即可 不需要加上lib 和 .a)
指定头文件的搜索路径,库文件的搜索路径以及具体使用哪个库。
依然是使用加法和快速幂函数
#include<stdio.h>
#include"add.h"
#include"get_m.h" int main()
{int a=2;int b=20;int res=add(a,b);int sum=get_m(a,b);printf("%d\n",res);printf("%d\n",sum);return 0;
}
但是这个a.out 不能直接执行。
即使使用了-I -L -l 依然没找到对应的动态库?
因为这三个选项只是在编译期间向编译器告知我们所使用的头文件和库文件的具体位置以及具体的库名。当可执行程序生成后就不再与编译器有直接的关系了,所以依然找不到此程序所依赖的动态库。
为了解决这个问题
(1).将库文件拷贝到系统共享的库路径下
sudo cp ./lib/libmath.so /lib64
但是与上面的静态库一样可能会对系统文件造成污染,一般不使用此方法。
(2).在系统共享路径建立同名软链接
sudo ln -s /home/pc/linuxplusplus/test39/libso/libmath.so /usr/lib/libmath.so
(3).更改环境变量 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/pc/linuxplusplus/test39/libso//(自己对应动态库所在路径)
LD_LIBRARY_PATH是程序运行动态查找库时所要搜索的路径,我们只需要将动态库所在目录路径添加到LD_LIBRARY_PATH环境变量中,程序运行起来就能找到对应的路径下的动态库。但是环境变量会在重启时自动重置,所以这种方法具有临时性。
(4)/etc/ld.so.conf.d/
在系统中/etc/ld.so.conf.d/是用于搜索动态库的路径,此路径下存放的全是后缀为.conf的配置文件,这些配置文件中所存放的都是动态库的路径。
所以将自己的库文件也放在这路径下,在可执行程序运行时,系统就可以找到我们的库文件。这种行为是永久的,不会因为重启改变。
将对应库文件地址写入一个.conf 文件中,然后将其导入/etc/ld.so.conf.d/路径,使用ldconfig指令更新以下配置文件,就可以执行可执行文件了
4.动静态库的使用
ldd 文件名 可以查看一个可执行程序所依赖的库文件,上面的libc.so.6就是该可执行程序所依赖的库文件,实际是一个软链接,这个软链接的原文件 libc-2.31.so 和libc.so.6在同一个目录下。
gcc与g++编译器默认都是动态链接的,如果非要静态链接,就只能在后面 -static 一旦 -static就必须存在相应的静态库。没有安装可以使用下面指令进行安装
centOS下sudo yum install glibc-static
sudo yum install libstdc++-staticunbento下sudo apt install glibc-static
sudo apt install libstdc++-static
这篇就到这里啦再见(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤
相关文章:

Linux:动静态库
1.库是什么,作用是什么 库是写好的,现有的可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始。 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存中执行。库有两种&#…...

鸿蒙跨平台框架ArkUI-X
01 引言 目前,移动端主流跨平台方案有Flutter、React Native、uni-app等等,还有刚推出不久的Compose-Multiplatform,真所谓是百花齐放。这些框架各有特点,技术实现各有差异,比如Flutter通过Dart编写的UI描述对接Flutte…...

第7章 wireshark(网络安全防御实战--蓝军武器库)
网络安全防御实战--蓝军武器库是2020年出版的,已经过去3年时间了,最近利用闲暇时间,抓紧吸收,总的来说,第7章开始学习抓包工具wireshark,如果你怀疑自己的电脑中毒了,那么用wireshark可以很轻松…...

【AI】神经网络|机器学习——图解Transformer(完整版)
Transformer是一种基于注意力机制的序列模型,最初由Google的研究团队提出并应用于机器翻译任务。与传统的循环神经网络(RNN)和卷积神经网络(CNN)不同,Transformer仅使用自注意力机制(self-attention)来处理输入序列和输出序列,因此可以并行计算,极大地提高了计算效率…...

002-SpringCloud-OpenFeign(远程调用)
SpringCloud-OpenFeign 1.引入依赖2.编写一个远程调用接口3.测试 1.引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency><dependencyManageme…...
基于类型的声明接收props
在 Vue 3 中,除了运行时声明这种常见方式,还可以通过基于类型的声明、解构赋值等方式来接收 props,下面为你详细介绍: 1. 基于类型的声明 这种方式借助 TypeScript 的类型系统来定义 props,具有类型检查和代码提示的…...
多方安全计算(MPC)电子拍卖系统
目录 一、前言二、多方安全计算(MPC)与电子拍卖系统概述2.1 多方安全计算(MPC)的基本概念2.2 电子拍卖系统背景与需求三、MPC电子拍卖系统设计原理3.1 系统总体架构3.2 电子拍卖中的安全协议3.3 数学与算法证明四、数据加解密模块设计五、GPU加速与系统性能优化六、GUI设计与系…...

使用QT + 文件IO + 鼠标拖拽事件 + 线程 ,实现大文件的传输
第一题、使用qss,通过线程,使进度条自己动起来 mythread.h #ifndef MYTHREAD_H #define MYTHREAD_H#include <QObject> #include <QThread> #include <QDebug>class mythread : public QThread {Q_OBJECT public:mythread(QObject* …...

【无人机路径规划】基于麻雀搜索算法(SSA)的无人机路径规划(Matlab)
效果一览 代码获取私信博主基于麻雀搜索算法(SSA)的无人机路径规划(Matlab) 一、算法背景与核心思想 麻雀搜索算法(Sparrow Search Algorithm, SSA)是一种受麻雀群体觅食行为启发的元启发式算法࿰…...

基于物联网技术的分布式光伏监控系统设计与实现
一、分布式光伏发电系统标准规范 1.常见应用场景 2.并网标准 Q/GDW1480-2015《分布式电源接入电网技术规定》 分布式电源并网电压等级可根据各并网点装机容量进行初步选择,推荐如下: 8kW 及以下可接入220V; 8kW~400kW可接入380V…...

阿里发布新开源视频生成模型Wan-Video,支持文生图和图生图,最低6G就能跑,ComFyUI可用!
Wan-Video 模型介绍:包括 Wan-Video-1.3B-T2V 和 Wan-Video-14B-T2V 两个版本,分别支持文本到视频(T2V)和图像到视频(I2V)生成。14B 版本需要更高的 VRAM 配置。 Wan2.1 是一套全面开放的视频基础模型&…...

27. Harmonyos Next仿uv-ui 组件NumberBox 步进器组件禁用状态
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! 文章目录 1. 组件介绍2. 效果展示3. 禁用状态设置3.1 整体禁用3.2 输入框禁用3.3 长按禁用 4. 完整示例代码5. 知识点讲解5.1 禁用状态属性5.2 禁用…...

【软件工程】一篇入门UML建模图(状态图、活动图、构件图、部署图)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀软件开发必练内功_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…...

AI智能导航站HTML5自适应源码帝国cms7.5模板
源码名称:AI导航站HTML5自适应源码帝国cms7.5模板 开发环境:帝国cms 7.5 安装环境:phpmysql var code "4d33ef8e-9e38-43b9-b37b-38f75944ecc9" 带软件采集,可以挂着自动采集发布,无需人工操作࿰…...
Redis 发布订阅模式详解:实现高效的消息通信
目录 引言 1. 什么是 Redis 发布订阅模式? 1.1 定义 1.2 核心概念 2. Redis 发布订阅的工作原理 2.1 基本流程 2.2 示例 2.3 频道与模式订阅 3. Redis 发布订阅的使用场景 3.1 实时消息通知 3.2 事件驱动架构 3.3 日志收集与分发 3.4 分布式锁与协调 4…...
ES的预置分词器
Elasticsearch(简称 ES)提供了多种预置的分词器(Analyzer),用于对文本进行分词处理。分词器通常由字符过滤器(Character Filters)、分词器(Tokenizer)和词元过滤器&#…...
MPPT与PWM充电原理及区别详解
MPPT(最大功率点跟踪)和PWM(脉宽调制)是太阳能充电控制器中常用的两种技术,它们在原理、效率和适用场景上有显著区别。以下是两者的详细对比: 1. 工作原理 PWM(脉宽调制) 核心机制…...
【AGI】通往AGI的复兴号:模型工具演进与技术路径优化
通往AGI的复兴号:模型工具演进与技术路径优化 一、核心模型与工具技术指标及场景分析1. 边缘计算标杆:GLM-PC(2024年11月)2. 长文本处理王者:DeepSeek R1(2025年1月)3. 轻量化开源代表ÿ…...
java2025年常见设计模式面试题
1. 请解释建造者模式(Builder Pattern)及其应用场景。 答案: 建造者模式用于创建一个复杂的对象,同时允许用户只通过指定复杂对象的类型和内容就能构建它们,隐藏了复杂的构建逻辑。 示例: public class C…...

探索CAMEL:揭开多智能体系统的神秘面纱
在人工智能领域,多智能体系统(Multi-Agent Systems, MAS)一直是一个充满活力和潜力的研究方向。随着大语言模型(LLM)的快速发展,智能体之间的协作与交互变得更加复杂和智能。今天,我们要介绍的是一个名为CAMEL(Communicative Agents for “Mind” Exploration of Large…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...

Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...

2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...
CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14
什么是 Pattern Matching(模式匹配) ❝ 模式匹配就是一种“描述式”的写法,不需要你手动判断、提取数据,而是直接描述你希望的数据结构是什么样子,系统自动判断并提取。❞ 你给的定义拆解: ✴ Instead of …...