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…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...