Linux库之动态库静态库

一、什么是库(Library)
二、库的分类
三、静态库、动态库优缺点
四、静态库的制作和使用
五、动态库的制作和使用
SO-NAME–解决主版本号之间的兼容问题
基于符号的版本机制
共享库系统路径
共享库的查找过程
有用的环境变量
gcc 编译器常用选项

Linux共享库、静态库、动态库详解

一、什么是库(Library)

在计算机编程中,库(Library)是一组预先编写好的可重用代码的集合,旨在为软件开发者提供特定功能或一组功能。库通常包含一组函数、例程、类、变量等,开发者可以在自己的程序中引用这些库以实现特定的任务,而无需编写相同的功能代码。

有两种主要类型的库:

  1. 静态库(Static Library): 静态库是在编译时与程序链接的,链接过程会将库的代码嵌入到最终的可执行文件中。这意味着可执行文件包含了程序和库的所有代码,使得程序可以独立运行,但也导致可执行文件的体积较大。静态库的文件通常具有.lib(在Windows上)或.a(在类Unix系统上)的扩展名。

  2. 动态库(Dynamic Library): 动态库是在运行时加载到内存中的,程序在需要时链接到库。这样,多个程序可以共享同一份库的实例,减小了可执行文件的体积。动态库的文件通常具有.dll(在Windows上)或.so(在类Unix系统上)的扩展名。

使用库的主要好处包括:

  • 代码重用: 可以使用库中的功能而不必重复编写相同的代码。
  • 模块化: 库可以被看作是程序的模块,有助于代码的组织和管理。
  • 可维护性: 对库的修改和升级可以在所有使用该库的程序中生效。

一些常见的编程库包括标准库(如C标准库、C++标准库)、图形库(如OpenGL)、网络库(如libcurl)、数学库(如NumPy)、GUI库(如Qt)、数据库访问库(如SQLite)。

库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容。

二、库的分类

库(Library)可以根据其使用和链接方式的不同分为不同的类型。主要的三种库类型包括:

  1. 静态函数库(Static Link Library): 静态库在编译时被链接到目标程序中,链接器将库的代码整合到最终的可执行文件中。这意味着目标程序独立于库文件,包含了库的实现。静态库的文件通常具有.lib(在Windows上)或.a(在类Unix系统上)的扩展名。静态库的优点是运行时不需要额外的加载步骤,但缺点是多个程序如果使用相同的库,会导致代码冗余。

  2. 共享函数库(Shared Library 或 Dynamic Link Library): 共享库在运行时被加载到内存中,而不是在编译时被链接到目标程序中。多个程序可以共享同一份库的实例,这减小了每个程序的体积。共享库的文件通常具有.dll(在Windows上)或.so(在类Unix系统上)的扩展名。共享库的优点是减小了可执行文件的体积,但需要在运行时动态加载,可能引入一些开销。

  3. 动态加载库(Dynamic Loading Library): 动态加载库是一种在程序运行时根据需要加载的库。程序可以在运行时选择性地加载和卸载这些库,而不是在程序启动时就加载全部。动态加载库通常与操作系统提供的动态链接库机制一起使用。这种方式允许程序更灵活地管理库的使用。

这三种库类型各有优缺点,选择取决于具体的应用场景和需求。

在这里插入图片描述

在Linux系统中,共享库(动态链接库)的命名规则通常遵循以下格式:

libname.so.x.y.z

其中各部分含义如下:

  • lib: 固定表示这是一个共享库文件。
  • name: 共享库的名称。
  • so: 固定表示这是一个共享对象(shared object)库。
  • x: 主版本号。当进行不兼容的更改时增加,通常表示库的接口发生了重大变化。
  • y: 次版本号。在保持向后兼容性的情况下进行的更改。
  • z: 发行版本号。通常表示对库的轻微更改或修复。

例如,如果一个库的名字是libexample.so,主版本号是1,次版本号是2,发行版本号是3,那么完整的库文件名可能是libexample.so.1.2.3

对于静态库,命名通常为:

libname.a

其中各部分含义相同,只是没有版本号,因为静态库在编译时已经被链接到可执行文件中,不涉及版本问题。

win平台下,静态库通常后缀为 .lib,动态库为 .dll
linux平台下,静态库通常后缀为 .a,动态库为 .so

1. 静态库

所谓静态库,就是在静态编译时由编译器到指定目录寻找并且进行链接,一旦链接完成,最终的可执行程序中就包含了该库文件中的所有有用信息,包括代码段、数据段等。

静态链接库在程序编译时会被链接到目标代码中,目标程序运行时将不再需要改动态库,加载速度快,移植方便,体积较大,浪费控件和资源,因为所有相关的对象文件与牵涉到库都被链接合成一个可执行文件,这样导致可执行文件的体积较大。

2. 动态库

所谓动态库,就是在应用程序运行时,由操作系统根据应用程序的请求,动态到指定目录下寻找并装载入内存中,同时需要进行地址重定向。

动态库在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入,因为可执行文件体积较小。有了动态库,程序的升级会相对比较简单,比如某个动态库升级了,只需要更换这个动态库的文件,而不需要去更换可执行文件。但要注意的是,可执行程序在运行时需要能找到动态库文件。

三、静态库、动态库优缺点

静态库:

优点:

1.静态库被打包到应用程序中加载速度快
2.发布程序无需提供静态库,因为已经在app中,移植方便

缺点:

1.链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝
2.更新、部署、发布麻烦

动态库:

优点:

1.链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存
2.程序升级简单,因为app里面没有库的源代码,升级之后只要库的名字不变,函数名以及参数不变,只是实现做了优化,就能加载成功。

缺点:

加载速度比静态库
发布程序需要提供依赖的动态库

四、静态库的制作和使用

(1)命名规则
静态库文件名的命名方式是“libxxxx.a”,库名前加“lib”,后缀用“.a”,“xxx”为静态库名。

(2)制作步骤
原材料:源代码 .c 或者 .cpp

.c文件生成 .o

gcc test.c -c

.o 打包
ar rcs 静态库的名字 原材料

ar rcs libxxxx.a test.o

(3)库的使用
-I(大写i):指定头文件搜索路径 默认默认路径 /usr/include/

-L: 指定库文件搜索路径

-l(小写L):链接名为libmycalc.a的共享库指定库的名字(去掉lib.a

-o:指定生成的最终应用程序的名字

gcc main.c -I /usr/include/ -L ./lib -lmycalc -o app

这个命令是将main.c文件编译成一个名为app的可执行文件,期间需要链接名为libmycalc.a的共享库,并且指定了头文件和库文件的搜索路径。

五、动态库的制作和使用

(1)命名规则
动态库的命名方式与静态库类似,前缀相同,为“lib”,后缀变为“.so”。所以为“libmytime.so”
(2)制作步骤

gcc -shared -fpic test.c -o libtest.so
-shared : 指定生成动态库
-fpic 	: 生成位置无关代码

(3)动态库的使用

gcc main.c -ltest -L ./ -o main

动态库优先从当前路径去找,没找到的话再去 /usr/lib/ 下去找通常动态库拷贝到 /usr/lib/ 下即可:

sudo cp libtest.so /usr/lib/

./main
动态库无法加载(引用动态库,怎么指定动态库的位置):
临时设置:在终端进行:export LD_LIBRARY_PATH=“动态库的路径”
export命令:环境变量设置

利用脚本

//创建一个.sh文件
vi start.sh

export LD_LIBRARY_PATH="/home/pi/test/动态库的路径"
./mianPrody//所要执行的程序名称
//在文件夹中输入以上内容
chmod +x start.sh
//给脚本加可执行的的权限
./start.sh
//执行该脚本

SO-NAME–解决主版本号之间的兼容问题

libname.so.x.y.z <-- libname.so.x
即创建一个只保持主版本号的符号链接到特定的共享库上。这样做的好处是,在编译链接、执行时始终使用符号链接来保持对于当前主版本更新的灵活性。使用gcc -l参数后面跟链接库名字就是链接某个库的意思。其中可以只使用-l name,链接器会自动寻找最新的版本。lc为根据输出文件来决定链接动态版本还是静态版本。

-Bdynamic为链接动态库, -static找静态库。

基于符号的版本机制

SO-NAME只解决主版本号的区分。次版本号可能存在不兼容,此时采用符号版本机制。大体策略就是讲共享库的符号按照版本划分为有依赖关系的集合,比如S1<-S2<-S3…<-SN表达了一个高版本依赖低版本的集合例子。编译时,用到了那些集合,就标记用到的最高版本的符号集合,比如某个可执行用到了S3符号集,那么它可以在包含大于S3的版本的系统中运行,否则链接器会负责报错。

共享库系统路径

大多数开源操作系统包括linux遵循FHS标准(File Hierarchy Standard,文件层级标准),规定了系统内每个目录该放什么东西。对于共享库相关的定义如下。

  • /lib,放最关键、最基础的共享库。如动态链接器、C语言运行库、数学库等主要被/bin和/sbin下程序用到的库。
  • /usr/lib/ 存放非运行时的关键性共享库,主要是开发时用到。
  • /usr/local/lib 存放和操作系统本身并不相关的库,一般是第三方程序的库。

共享库的查找过程

首先,可执行程序和共享库中在.dynamic段中的DT_NEED类型中的项表明了可执行程序、共享库所依赖的共享库。如果是绝对路径,则去找那个路径。如果是相对路径,则首先在LD_LIBRARY_PATH环境变量中定义的路径下查找,之后在/etc/ld.so.conf定义的目录中查找(但是一般这个步骤只在缓存中查找即使用ldconfig来进行缓存,然后链接器在/etc/ld.so.cacha中查找),最后再/lib和/usr/lib中查找。如果还没有则宣告失败。在编译链接时期LD_LIBRARY_PATH相当于gcc附加的-L选项。

有用的环境变量

  • LD_LIBRARY_PATH,编译时相当于gcc中附件-L选项, 运行时告诉链接器首先在这个变量定义的目录中查找相对路径依赖库。
  • LD_PRELOAD, 指定预先装载的共享库或者目标文件,优先于LD_LIBRARY_PATH。由于全局符号介入,LD_PRELOAD中定义的符号会覆盖以后加载的符号,可以实现更方便的debug(覆盖某些函数,添加打印信息)。
  • LD_DEBUG,可以指定在动态链接库发挥作用时打印的信息,可以设置的值有:
    • "files"显示整个装载过程
    • "bindings"显示动态链接符号绑定过程
    • "libs"显示动态链接库的查找过程
    • "versions"显示符号版本的依赖关系
    • "reloc"显示重定位过程
    • "symbols"显示符号表查找过程
    • "statistics"显示动态链接过程中的各种统计信息
    • "all"显示所有信息
    • "help"显示上面的可选值的帮助信息

gcc 编译器常用选项

下面是关于gcc编译器常用选项的简要说明:

选项含义
-o output_file指定输出文件的名称。
-c生成目标文件(.o),但不进行链接,用于编译源文件。
-I include_path指定头文件搜索路径。
-L library链接时使用指定的库。
-e entry_point指定程序的入口点,用于生成可执行文件。
-Wall启用警告信息。
-g生成调试信息。
-std=standard指定使用的C或C++标准。
-pthread在编译和链接时启用POSIX线程支持。
-Dmacro定义宏。
-Olevel指定优化级别。
-lm链接数学库。
-lrt链接实时库。
-lpthread链接POSIX线程库。
-shared生成共享库。

以上是一些常用的gcc选项,具体用法可以根据编译的需求进行调整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/201154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32F1外部中断EXTI

目录 1. EXTI简介 2. EXTI基本结构 3. AFIO复用IO口 4. EXTI框图 5. EXTI程序配置 5.1 首先先配置要使用的GPIO口的引脚 5.2 配置AFIO数据选择器&#xff0c;选择想要中断的引脚 5.3 EXTI配置 1. EXTI简介 EXTI&#xff08;Extern Interrupt&#xff09;外部中…

思腾云计算中心 | 5千平米超大空间,基础设施完善,提供裸金属GPU算力租赁业务

2021年&#xff0c;思腾合力全资收购包头市易慧信息科技有限公司&#xff0c;正式开启云计算业务。思腾云计算中心占地2400平米&#xff0c;位于包头市稀土高新区&#xff0c;毗邻多家知名企业&#xff0c;地理位置优越&#xff0c;交通便利&#xff0c;是区内重要的信息化产业…

配置集群免密登录

文章目录 前言配置集群免密登录1. 设置主机名与 IP 地址的映射关系2. 生成 SSH 密钥对3. 将公钥复制到集群节点4. 测试免密登录5. 配置节点之间互相免密登录 总结 前言 本文介绍了如何配置集群之间免密登录&#xff0c;以便在搭建集群环境时方便地进行节点之间的通信。通过设置…

【开源】基于Vue.js的公司货物订单管理系统

文末获取源码&#xff0c;项目编号&#xff1a; S 082 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S082。} 文末获取源码&#xff0c;项目编号&#xff1a;S082。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 客户管理模块2.2 商品维护模块2.3 供…

19、pytest通过mark标记测试函数

官方实例 [pytest] markers slow:marks tests as slow(deselect with -m "not slow")serial# content of test_mark.py import pytestpytest.mark.slow def test_mark_function():print("test_mark_function was invoked")assert 0解读与实操 通过使用p…

FairGuard无缝兼容小米澎湃OS、ColorOS 14 、鸿蒙4!

随着移动互联网时代的发展&#xff0c;各大手机厂商为打造生态系统、构建自身的技术壁垒&#xff0c;纷纷投身自研操作系统。 而对于一款游戏安全产品&#xff0c;在不同操作系统下&#xff0c;是否能够无缝兼容并且提供稳定的、高强度的加密保护&#xff0c;成了行业的一大痛…

7、信息收集(2)

文章目录 一、目录扫描1.1 目录扫描的原因1.2 目录扫描方法 二、指纹识别2.1 系统指纹识别2.2 中间件指纹识别2.3 web程序指纹识别2.4 防火墙指纹识别2.5 其他工具使用 三、Google Hacking3.1 逻辑运算符3.2 基本语法3.3 相关案例 一、目录扫描 1.1 目录扫描的原因 寻找网站后…

docker中mysql的数据迁移

在Docker中进行MySQL数据迁移通常涉及将数据从一个MySQL容器导出&#xff0c;并将其导入到另一个容器或主机上的MySQL实例中。以下是一般步骤&#xff1a; 步骤 1: 在源 MySQL 容器中导出数据 进入源 MySQL 容器&#xff1a; docker exec -it <source_mysql_container_name…

翻译: 大语言模型LLMs能做什么和不能做什么 保存笔记What LLMs can and cannot do

生成式 AI 是一项惊人的技术&#xff0c;但它并非万能。在这个视频中&#xff0c;我们将仔细看看大型语言模型&#xff08;LLM&#xff09;能做什么&#xff0c;不能做什么。我们将从我发现的一个有用的心理模型开始&#xff0c;了解它能做什么&#xff0c;然后一起看看 LLM 的…

怎么验证公钥和私钥是一对

文章目录 前言ssh-keygen 和 openssl两种证书的内容对比 从私钥提取公钥OPENSSH和PEM两种密钥格式相互转化OpenSSH 格式私钥转换成 OpenSSL PEM 格式私钥OpenSSL PEM 格式私钥转换成 OpenSSH 格式私钥OpenSSH 格式公钥生成 OpenSSL PEM 格式公钥OpenSSL PEM 格式公钥生成 OpenS…

【Azure 架构师学习笔记】- Azure Databricks (2) -集群

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (1) - 环境搭建 前言 在上文中提到了ADB 的其中一个核心就是集群&#xff0c;所以这里专门研究一下ADB 的集群。 ADB 集群 首先了解一下ADB…

《SpringBoot项目实战》第六篇—接口防抖(防重复提交)的一些方式

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 第六篇—接口防抖(防重复提交)的一些方式 本文参考项目源码地址&#xff1a;summo-springboot-i…

SpringBoot基础知识

SpringBoot简介 回顾什么是Spring Spring是一个开源框架&#xff0c;2003 年兴起的一个轻量级的Java 开发框架&#xff0c;作者&#xff1a;Rod Johnson 。 Spring是为了解决企业级应用开发的复杂性而创建的&#xff0c;简化开发。 Spring是如何简化Java开发的 为了降低Ja…

记录:Unity脚本的编写9.0

目录 射线一些准备工作编写代码 突然发现好像没有写过关于射线的内容&#xff0c;我就说怎么总感觉好像少了什么东西&#xff08;心虚 那就在这里写一下关于射线的内容吧&#xff0c;将在这里实现射线检测鼠标点击的功能 射线 射线是一种在Unity中检测碰撞器或触发器的方法&am…

22、pytest多个参数化的组合

官方实例 # content of test_multi_parametrie.py import pytestpytest.mark.parametrize("x",[0,1]) pytest.mark.parametrize("y",[2,3]) def test_foo(x,y):print("{}-{}".format(x,y))pass解读与实操 要获得多个参数化参数的所有组合&…

什么是HTTP/2?它与HTTP/1.x相比有什么改进?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

《论文阅读》使用条件变分自动编码器学习神经对话模型的语篇水平多样性 2017 ACL

《论文阅读》使用条件变分自动编码器学习神经对话模型的语篇水平多样性 2017 ACL 前言简介相关知识Stochastic Gradient Variational BayesMultivariate Gaussian DistributionIsotropic Gaussian DistributionReparameterization Trickprior network & posterior network …

简述Blender

前言 Blender是一款免费开源的3D计算机图形软件&#xff0c;功能强大&#xff0c;包括建模、动画、渲染、视频剪辑等多个方面。下面我分别为你介绍Blender的基础、提升、优势和应用领域。 介绍 Blender是由Blender基金会开发的开源项目&#xff0c;最初设计为一个内部工具&a…

C++ 函数详解

目录 函数概述 函数的分类 函数的参数 函数的调用 函数的嵌套调用 函数的链式访问 函数声明和定义 函数递归 函数概述 函数——具有某种功能的代码块。 一个程序中我们经常会用到某种功能&#xff0c;如两数相加&#xff0c;如果每次都在需要用到时实现&#xff0c;那…

第4章 互联网

文章目录 4.1 计算机网络基础 94 4.1.1 计算机网络的基本概念 94 4.1.2 局域网的基本原理 96 4.1.3 局域网协议与应用 98 4.2 Internet 100 4.2.1 TCP/IP 101 4.2.2 TCP/IP应用 106 4.2.3 网络操作系统的功能 112 4.2.4 网络安全的概念 116 4.3 计算机软件编程基础 …