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

el-pagination的使用说明
<el-paginationv-model:current-page"pageNo" //当前第几页v-model:page-size"pageSize" //每页显示多少条数据:page-sizes"[10, 20, 30]" //控制每页显示的条数:small"true" //控制分页器大小:disabled&quo…...

UniApp 运行的微信小程序如何进行深度优化
UniApp 运行的微信小程序如何进行深度优化 目录 引言性能优化 1. 减少包体积2. 优化页面加载速度3. 减少 setData 调用4. 使用分包加载 代码优化 1. 减少不必要的代码2. 使用条件编译3. 优化图片资源 用户体验优化 1. 优化交互体验2. 预加载数据3. 使用骨架屏 调试与监控 1. …...

Web Worker如何在本地使用
首先了解一下什么是Web Worker Web Worker 是一种在后台线程中运行 JavaScript 的机制,允许你在不阻塞主线程的情况下执行耗时的任务。这对于保持网页的响应性和流畅性非常重要,特别是在需要进行复杂计算或大量数据处理时。 主要特点 多线程࿱…...

[原创](Modern C++)现代C++的关键性概念: 改掉new习惯, 尽情地使用智能分配内存
[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、C …...

C/C++中使用CopyFile、CopyFileEx原理、用法、区别及分别在哪些场景使用
文章目录 1. CopyFile原理函数原型返回值用法示例适用场景 2. CopyFileEx原理函数原型返回值用法示例适用场景 3. 核心区别4. 选择建议5. 常见问题6.区别 在Windows系统编程中,CopyFile和CopyFileEx是用于文件复制的两个API函数。它们的核心区别在于功能扩展性和控制…...

android studio开发文档
android基本样式 1.文本 2.设置文本大小 3.字体颜色 背景 资源文件 xml’引用资源文件 4.视图宽高 5.间距 6.对齐方式 常用布局 1.linearLayout线性布局 2.相对布局 RelativeLayout 3.网格布局GridLayout 4.scrollview滚动视图 Button 点击事件与长按事件 长按 按钮禁用与…...

计算机网络笔记(二)——1.2互联网概述
1.2.1网络的网络 起源于美国的互联网现已发展成为世界上最大的覆盖全球的计算机网络。 下面,我们先来看看关于网络、互连网、互联网(因特网)的一些基本概念。为了方便,后面我们所称呼的"网络"往往就是"计算机网络",而不是电信网或有…...

Ubuntu 24.04.2 允许 root 登录桌面、 ssh 远程、允许 Ubuntu 客户机与主机拖拽传递文件
允许 root 登录桌面 修改 /etc/pam.d/gdm-autologin , /etc/pam.d/gdm-password 加 # 以注释掉 auth required pam_succeed_if.so user ! root quiet_success 允许 root 通过 ssh 登录 修改 /etc/ssh/sshd_config ... #PermitRootLogin prohibit-password PermitRootLogin …...

day18-后端Web开发——Maven高级
目录 Maven高级1. 分模块设计与开发1.1 介绍1.2 实践1.2.1 分析1.2.2 实现 1.3 总结 2. 继承与聚合2.1 继承2.1.1 继承关系2.1.1.1 思路分析2.1.1.2 实现2.1.2 版本锁定2.1.2.1 场景2.1.2.2 介绍2.1.2.3 实现2.1.2.4 属性配置 2.2 聚合2.2.1 介绍2.2.2 实现 2.3 继承与聚合对比…...

华为hcia——Datacom实验指南——三层交换和ARP的工作原理
什么是三层交换 三层交换是指连接在同一台三层交换机上,不同vlan用户,不同网段ip,通过vlanif接口进行数据交换。 什么是ARP协议 通过网络层的ip地址解析成数据链路层的mac地址。 说白了就是通过目标ip地址去问他对应的mac地址是多少。 A…...