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

Linux:动静态库

1.库是什么,作用是什么

库是写好的,现有的可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始。

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存中执行。库有两种:

静态库后缀   .a (在linux下)   .lib (在windows下)

动态库后缀   .so (在linux下)   .dll  (在windows下)

 静态库

静态库 (.a):程序在编译链接的时候把库里的代码链接到可执行文件中链接完后,静态库的代码就成为了目标文件的一部分,如果多个程序使用同一个静态库,那么每个程序都会包含一份该库的副本,从而导致程序体积较大。然后程序运行的时候不再需要静态库了。

优点:

  1. 独立性高
    静态库在编译时直接嵌入到可执行文件中,程序运行时无需依赖外部库文件,减少了部署时的依赖问题。

  2. 执行效率高
    代码在编译时已完全链接,运行时无需加载外部库,启动速度和执行效率通常更快。

  3. 部署简单
    可执行文件是独立的,无需额外分发或配置库文件,适合嵌入式系统或封闭环境。

  4. 兼容性问题少
    无需担心库版本与系统环境不匹配的问题。

缺点:

  1. 文件体积大
    每个可执行文件都包含库代码的副本,占用更多磁盘和内存空间(尤其是多个程序使用同一库时)。

  2. 更新困难
    库的更新需要重新编译整个程序,维护成本高,无法快速修复漏洞。

  3. 内存冗余
    多个程序运行时,相同库代码的多个副本会重复占用内存。

 动态库

动态库(.so):程序运行时才去链接动态库的代码,多个程序共享使用库的代码。

一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码,在运行前,外部函数的机器码有操作系统从磁盘上的该动态库中赋值到内存中,这个过程叫做动态链接。

动态库可以在多个程序间共享,所以动态链接使可执行文件更小,节省了磁盘空间。操作系统通过虚拟内存机制 允许物理内存中的一份动态库被所有用到该库的进程共用,节省内存和磁盘空间。

优点:

  1. 节省资源
    多个程序共享同一动态库文件,减少磁盘和内存占用。

  2. 更新便捷
    替换动态库文件即可更新功能或修复漏洞,无需重新编译程序。

  3. 支持运行时加载
    可实现插件机制或延迟加载,灵活扩展程序功能。

  4. 编译效率高
    链接时仅记录引用,编译速度较快(尤其是大型项目)。

缺点:

  1. 依赖管理复杂
    程序运行时需确保系统中存在正确版本的动态库,否则会崩溃(如“DLL地狱”)。

  2. 性能略低
    首次加载库时需要额外开销,可能影响启动速度。

  3. 兼容性风险
    若动态库接口或行为变更,可能导致依赖它的程序异常(需严格版本控制)。

  4. 部署稍复杂
    需确保目标环境已安装所需动态库,或与程序一起分发。

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.库是什么&#xff0c;作用是什么 库是写好的&#xff0c;现有的可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始。 本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作系统载入内存中执行。库有两种&#…...

鸿蒙跨平台框架ArkUI-X

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

第7章 wireshark(网络安全防御实战--蓝军武器库)

网络安全防御实战--蓝军武器库是2020年出版的&#xff0c;已经过去3年时间了&#xff0c;最近利用闲暇时间&#xff0c;抓紧吸收&#xff0c;总的来说&#xff0c;第7章开始学习抓包工具wireshark&#xff0c;如果你怀疑自己的电脑中毒了&#xff0c;那么用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 中&#xff0c;除了运行时声明这种常见方式&#xff0c;还可以通过基于类型的声明、解构赋值等方式来接收 props&#xff0c;下面为你详细介绍&#xff1a; 1. 基于类型的声明 这种方式借助 TypeScript 的类型系统来定义 props&#xff0c;具有类型检查和代码提示的…...

多方安全计算(MPC)电子拍卖系统

目录 一、前言二、多方安全计算(MPC)与电子拍卖系统概述2.1 多方安全计算(MPC)的基本概念2.2 电子拍卖系统背景与需求三、MPC电子拍卖系统设计原理3.1 系统总体架构3.2 电子拍卖中的安全协议3.3 数学与算法证明四、数据加解密模块设计五、GPU加速与系统性能优化六、GUI设计与系…...

使用QT + 文件IO + 鼠标拖拽事件 + 线程 ,实现大文件的传输

第一题、使用qss&#xff0c;通过线程&#xff0c;使进度条自己动起来 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)

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

基于物联网技术的分布式光伏监控系统设计与实现

一、分布式光伏发电系统标准规范 1.常见应用场景 2.并网标准 Q/GDW1480-2015《分布式电源接入电网技术规定》 分布式电源并网电压等级可根据各并网点装机容量进行初步选择&#xff0c;推荐如下&#xff1a; 8kW 及以下可接入220V&#xff1b; 8kW~400kW可接入380V&#xf…...

阿里发布新开源视频生成模型Wan-Video,支持文生图和图生图,最低6G就能跑,ComFyUI可用!

Wan-Video 模型介绍&#xff1a;包括 Wan-Video-1.3B-T2V 和 Wan-Video-14B-T2V 两个版本&#xff0c;分别支持文本到视频&#xff08;T2V&#xff09;和图像到视频&#xff08;I2V&#xff09;生成。14B 版本需要更高的 VRAM 配置。 Wan2.1 是一套全面开放的视频基础模型&…...

27. Harmonyos Next仿uv-ui 组件NumberBox 步进器组件禁用状态

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

【软件工程】一篇入门UML建模图(状态图、活动图、构件图、部署图)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…...

AI智能导航站HTML5自适应源码帝国cms7.5模板

源码名称&#xff1a;AI导航站HTML5自适应源码帝国cms7.5模板 开发环境&#xff1a;帝国cms 7.5 安装环境&#xff1a;phpmysql var code "4d33ef8e-9e38-43b9-b37b-38f75944ecc9" 带软件采集&#xff0c;可以挂着自动采集发布&#xff0c;无需人工操作&#xff0…...

Redis 发布订阅模式详解:实现高效的消息通信

目录 引言 1. 什么是 Redis 发布订阅模式&#xff1f; 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&#xff08;简称 ES&#xff09;提供了多种预置的分词器&#xff08;Analyzer&#xff09;&#xff0c;用于对文本进行分词处理。分词器通常由字符过滤器&#xff08;Character Filters&#xff09;、分词器&#xff08;Tokenizer&#xff09;和词元过滤器&#…...

MPPT与PWM充电原理及区别详解

MPPT&#xff08;最大功率点跟踪&#xff09;和PWM&#xff08;脉宽调制&#xff09;是太阳能充电控制器中常用的两种技术&#xff0c;它们在原理、效率和适用场景上有显著区别。以下是两者的详细对比&#xff1a; 1. 工作原理 PWM&#xff08;脉宽调制&#xff09; 核心机制…...

【AGI】通往AGI的复兴号:模型工具演进与技术路径优化

通往AGI的复兴号&#xff1a;模型工具演进与技术路径优化 一、核心模型与工具技术指标及场景分析1. 边缘计算标杆&#xff1a;GLM-PC&#xff08;2024年11月&#xff09;2. 长文本处理王者&#xff1a;DeepSeek R1&#xff08;2025年1月&#xff09;3. 轻量化开源代表&#xff…...

java2025年常见设计模式面试题

1. 请解释建造者模式&#xff08;Builder Pattern&#xff09;及其应用场景。 答案&#xff1a; 建造者模式用于创建一个复杂的对象&#xff0c;同时允许用户只通过指定复杂对象的类型和内容就能构建它们&#xff0c;隐藏了复杂的构建逻辑。 示例&#xff1a; public class C…...

探索CAMEL:揭开多智能体系统的神秘面纱

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

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...

命令行关闭Windows防火墙

命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)​方法二:CMD命令…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...