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

Linux的库文件

目录

概述:

静态库:

静态库概述:

静态库的制作

共享库(动态库)

共享库概述

动态库制作

动态库临时生效

动态库长期生效

动态库的升级

位置无关代码


概述:

库文件一般就是编译好的二进制文件,用于在链接阶段同目标代码一块生成可执行文件,或者运行可执行文件的时候被加载,以遍调用库文件中的某段代码。

动态链接都是索引的.so文件,静态链接都是压缩打包的.a文件。

库文件和可执行文件相比:

  • 相同点:两者都是编译好的二进制文件
  • 不同点:库文件没法直接执行(直观上看,他的源代码中没有main函数,而只是一些函数模块的定义和实现,没有运行的入口主函数,所以库文件没法直接执行)。

我们的程序开发,无论是运行的时候,还是编译,链接的时候,一般都需要借助一些库来实现他们的功能,而很少直接通过程序的源代码生成完全独立的可执行文件。

静态库:

静态库概述:

        静态库实际上就是一些目标文件的(一般是以.o结尾)的集合,静态库一般是以.a结尾,只用于链接生成可执行文件阶段。

具体来说,以c程序为例子,一般我们编译程序源代码的时候过程大致是:

  • 以.c为后缀的源文件经过编译生成.o文件的目标文件
  • 以.o为后缀的目标文件经过链接生成最终的可执行文件。

我们可以在链接的时候直接链接.o的目标文件,也可以将这些.o文件打包集中起来,统一链接,而生成的打包集成了所有.o文件,也就是静态库。

        静态库只在程序连接的时候时候,连接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中,一旦链接完成生成可执行文件之后,执行程序的时候就不再需要静态库了

        由于每一个静态库的应用程序都是需要拷贝所用到的函数的代码,所以静态库链接生成可执行文件会比较大,多个程序运行的时候占用的内存空间比较大,(每个程序在内存中都有一份复制的静态库代码),但是由于运行的时候不用从外部动态加载额外的库了,速度会比共享库快。

静态库的制作

实例:假设在实际工作中设计了两个算法,但是需要卖给其他公司使用,为了保护公司的知识产权是不能将源代码交给其他公司的,这样我们可以将两个算法封装或者打包到一个静态库中。

假设实现这两个算法的函数为func1()和func()2。

新建一个头文件hello.h,在hello.h中对两个函数进行声明:

编写一个简单的程序“hello.c”

将hello.c编译生成.o文件

gcc -c hello.c -o hello.o

使用ar命令(ar是archive的意思)将hello.o文件打包成一个静态库文件libhello.a

 ar rcs libhello.a hello.o

注意:

  1. 如果需要将多个.o文件打包成文件库,则在命令行后边填写所有.o文件的名字即可
  2. 生成的库的名字必须是libxxx.a格式(注意:这里是尽量最好使用lib开头的格式,因为其他格式的编译方式是不一样的)

编译参数:<rcs>

r:表明将模块加入到静态库中,c表示创建静态库,s表示产生索引

使用nm命令查看库文件中包含的符号:nm libhello.a

使用 ar -t 命令查看静态库是由那些.o文件组成的:ar -t libhello.a

编写一个带有主函数的程序main.c,并且在main.c中调用静态库中的func1和func2函数:

现在所有文件下都在同一个目录下,没法直接体现出来静态库的作用。

在IO_file_test目录下新建一个static_lib_test目录进行测试将文件移动到下边设备树结构。(这里是一个比较常用的目录结构,但是为了方便测试三个文件都放在一个文件目录下即可)

解释:

include目录下是.h文件

lib里边是链接的静态库文件

src里边是.c文件

编译:

gcc main.c -L../lib -lhello -I../include -o main

编译解释:

-L指向的是链接的静态库路径

-l(小L)是静态库的命称(去掉lib之后的)

-I(大i)链接存放.h文件的路径

编译现象:

在静态库的概述中会标红的地方提到了(一旦链接完成生成可执行文件之后,执行程序的时候就不再需要静态库了),所以这时删除掉libhello.a文件后程序仍然可以执行。

共享库(动态库)

共享库概述

共享库也叫做动态库

静态库缺点:

  1. 内存消耗大;(假设一个静态库的大小为1M,当两千个程序都用到这库将消耗掉2G内存)
  2. 当静态库中的代码优化的时候,所有调用该静态库的程序需要重新编译,这样太过与麻烦。

动态库特点:

  1. 动态库在程序编译的时候并不会被链接到目标代码当中,而是在程序运行的时候才被载入。
  2. 不同的应用程序如果调用相同的库,那么在内存中里只需要有一份共享库的实例,规避了空间浪费问题。
  3. 动态库在程序运行的时候才能被载入,也解决了静态库对程序的更新,部署和发布页带来的麻烦。用户只需要更新动态库即可,增量更新。

动态库制作

参照静态库目录下创建三个文件如下:内容和静态库的也相同

编译链接生成.o文件

将编译好生成好的hello.o编译编译生成动态库:gcc -shared -fPIC -o libhello.so hello.o

注意:

  1. -shared:表明是使用的共享库
  2. -fPIC:表明生成与位置无关的代码、
  3. 动态库后缀为.so
  4. 动态库格式libxxx.so
  5. 如果还有其他链接的.o文件,直接在hello.o后边加上,用空格隔开

使用nm命令查看一个库文件中包含的符号: nm libhello.so

对照静态库测试目录制作动态库目录格式:

将上边共享库目录的文件对应拷贝到共享库测试目录里边如下:

进行编译:gcc main.c -L../lib -lhello -I../include -o main

但是如果直接执行的话,编译器会爆出一个错误。

错误的主要意思是在加载的时候打不开动态库文件,但是注意:动态库在在程序执行的时候会被加载。

这是因为在Linux中启动一个ELF格式的二进制可执行文件会自动启动和运行一个program loader(程序加载器:用来加载一些库)。对于Linux系统,这个loader的名字是ld-linux.so.X(X是版本号)。这个loader启动后会load所有的其他本程序的要使用的共享函数库。动态库与静态库不同,在执行文件的阶段需要加载动态库文件,而加载的动态库文件需要在指定位置或者添加在环境变量中,才能正确的加载动态库文件。

动态链接库的查找先后顺序:

  • LD_LIBRARY_PATH环境变量中的路径
  • /etc/ld.so.cache缓存文件
  • /usr/lib和/lib

动态库临时生效

可以临时将libhello.so所在的路径追加到环境变量LD_LIBRARY_PATH中

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/book/Desktop/IO_file_test/shared_lib_test/lib

冒号后边跟是自己的动态库路径。

修改完成之后我们可以使用echo $LD_LIBRARY_PATH查看环境变量被修改的值

注意: 在终端使用expert命令来修改当前环境变量的值,只是对当前会话临时生效,如果切换到一个新的会话窗口或者新的终端,关闭当前会话窗口都会失效。

动态库长期生效

  • 修改系统启动配置文件,将export命令添加到启动文件当中

设置环境变量:
      1.打开 vim ~/.bashrc 文件
       2.在文件末尾添加一行
            export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径(如果需要删除环境变量,需要在~/.bashrc中删除环境变量后,关掉终端,重新启动终端才能生效)

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/book/Desktop/IO_file_test/shared_lib_test/lib
       3.重新加载配置文件 source ~/.bashrc

  • 将动态库文件拷贝到/usr/lib或者/lib目录下(一般不采用这个种方式,因为这样会污染系统,并且不方便项目迁移)
  • 修改/etc/ld.so.conf文件

动态库的升级

引入:

在实际工作当中,我们可能经常需要对动态库的板本进行升级,假如原来的库为libhello.so,那么升级完以后还需要保留每一个旧的板本,动态库的名字就不能重复,但是程序在加载的时候只加载libhello.so文件,解决:所以我们可以对每一个板本的动态库文件进行不同的命名,然后在新建立软链接,链接需要使用的实体库即可。

根据动态的命名规则,我们可以将动态库的第一个板本命名为:libhello.so.1.0.0,然后创建软连接

ln -s libhello.so.1.0.0 libhello.so

假设我们在原来的库上增加了某些接口我们可以将新库的版本名命名为libhello.so.1.1.0,删除原来的软连接文件,并重新创建软链接文件到该文件。

位置无关代码

        位置无关代码(PIC:position-independent code),也被称为地址无关代码,是指源代码被编译成二进制文件(可以是执行文件也可以是某个库文件),编码方式也和位置(地址)无关。

        程序在运行的时候是需要被加载到物理内存上运行的,但是操作系统为了方便每个进程进行内存管理,使用虚拟内存技术,每一个进程运行时都会得到4G的虚拟内存。这个虚拟内存可以认为每个进程任务自己认为自己有4G的空间,着只是每个进程认为的,但是实际上,在虚拟内存对应的物理内存上,可能只对应一点点的物理内存,实际用了多少内存,就会对应多少物理内存。

使用静态库和动态库编译生成的可执行文件在运行时候在内存上的加载方式:

如果使用了静态库编译可执行程序,每个函数在内存中的位置(地址)在编译完成以后就已经决定了。

但是共享库(动态库)是在可执行程序执行的时候加载进去的,动态编译后的函数的调用地址是自动计算出来的,这就是与位置无关的代码。

下边是找到的一个资料对位置无关代码的验证:

在64为机器上可以运行32位的指令。

相关文章:

Linux的库文件

目录 概述&#xff1a; 静态库&#xff1a; 静态库概述&#xff1a; 静态库的制作 共享库&#xff08;动态库&#xff09; 共享库概述 动态库制作 动态库临时生效 动态库长期生效 动态库的升级 位置无关代码 概述&#xff1a; 库文件一般就是编译好的二进制文件&…...

JAVA Web 学习(五)Nginx、RPC、JWT

十二、反向代理服务器——Nginx 支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量&#xff0c;其占用内存少、并发能力强、能支持…...

Python编程的十大神奇依赖库

Python是一门广受欢迎的编程语言&#xff0c;其生态系统丰富多彩&#xff0c;拥有许多令人惊叹的依赖库&#xff0c;可以帮助程序员们在各种领域中创造出令人瞠目结舌的应用。在这篇文章中&#xff0c;我们将探讨Python编程的十大神奇依赖库&#xff0c;它们像魔法一样&#xf…...

Java类的继承

XHTMLMapper继承 XWPFDocumentVisitor&#xff1a; 由于endVisitTableCell是抽象方法&#xff0c;XHTMLMapper中必须要实现&#xff1b; existErr()子类是否重写都是自由的&#xff1b; public abstract class XWPFDocumentVisitor<T, O extends Options, E extends IXWPFM…...

【DC渗透系列】DC-4靶场

主机发现 arp-scan -l┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:6b:ed:27, IPv4: 192.168.100.251 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.100.1 00:50:56:c0:00:08 …...

开源软件全景解析:驱动技术创新与行业革新的力量

目录 什么是开源 开源的核心 开源软件的特点 为什么程序员应该拥抱开源 1.学习机会&#xff1a; 2.社区支持&#xff1a; 3.提高职业竞争力&#xff1a; 4.加速开发过程&#xff1a; 5.贡献和回馈&#xff1a; 开源软件的影响力 开源软件多元分析&#xff1a; 开源…...

目标检测及相关算法介绍

文章目录 目标检测介绍目标检测算法分类目标检测算法模型组成经典目标检测论文 目标检测介绍 目标检测是计算机视觉领域中的一项重要任务&#xff0c;旨在识别图像或视频中的特定对象的位置并将其与不同类别中的对象进行分类。与图像分类任务不同&#xff0c;目标检测不仅需要…...

跟着cherno手搓游戏引擎【20】混合(blend)

抽象&#xff1a; Renderer.h: #pragma once #include"RenderCommand.h" #include "OrthographicCamera.h" #include"Shader.h" namespace YOTO {class Renderer {public:static void Init();static void BeginScene(OrthographicCamera& …...

leetcode 3.无重复字符的最长字串(滑动窗口) (C++)DAY2

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示…...

Android Build 依赖项

在项目中的Build.Gradle文件中dependencies代码块中添加指定依赖项。 有三种不同类型的依赖项 本地模块依赖项 implementation project(:mylibrary)这个mylibrary 必须在 settings.gradle 中使用的库名称相同 本地文件依赖项 implementation fileTree(dir: libs, include:…...

SpringMVC精简知识点

SpringMVC 数据格式化基本数据类型和字符串自动转换特殊数据类型和字符串自动转换 验证及国际化应用实例注意事项和使用细节注解的结合使用数据类型转换校验核心类-DatBinder取消某个属性的绑定中文乱码解决处理json和HttpMessageConverter<T>作业布置SpringMVC文件上传自…...

如何写好论文——(17)如何用批判性思维检阅文献

在写论文的时候&#xff0c;往往需要引用很多文献资料&#xff0c;作为论点来证明我们的研究目标是合理的。在讨论和结论中&#xff0c;我们往往也需要引用很多的文献资料和我们自己的研究结果放在一起&#xff0c;来证明我们的研究结果是有意义的。所以在选择文献资料的时候&a…...

git将项目的某次签入遴选(Cherry-Pick)另一个项目

需求&#xff1a;将项目Product&#xff0c;分支feature/platform&#xff0c;签入959294ce6b75ee48c5cb22c46d7398654628a896&#xff0c;遴选到项目BRP&#xff0c;分支dev 第一步&#xff1a;使用原签入生成patch文件&#xff08;git format-patch -1 <commit_hash>&a…...

开源节点框架STNodeEditor使用

节点&#xff0c;一般都为树形Tree结构&#xff0c;如TreeNode&#xff0c;XmlNode。 树形结构有其关键属性Parent【父节点】&#xff0c;Children【子节点】 LinkedListNode为链表线性结构&#xff0c;有其关键属性Next【下一个】&#xff0c;Previous【上一个】&#xff0c…...

算法每日一题: Nim游戏 | 找规律

哈哈&#xff0c;大家好&#xff0c;我是星恒&#xff0c;今天的每日一题真开心&#xff0c;连做了3天牢&#xff0c;终于ak了一道&#xff0c;太不容易了 这道题其实就是找规律&#xff0c;刚开始我还以为是动归&#xff0c;但是列举了不少例子之后&#xff0c;发现有自己直接…...

分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别

分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别 目录 分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现G…...

Dockerfile保留字

目录 一、Dockerfile保留字是什么&#xff1f; 二、Docker构建流程 1. 从基础镜像运行容器 2. 执行指令并修改容器 3. 提交新的镜像层 4. 基于新镜像运行新容器 5. 执行下一条指令 6. 循环执行指令 7. 所有指令执行完成 三、保留字 1. FROM 使用基础镜像作为起点 2.…...

Linux的7个运行级别

目录 1、有那7个运行级别&#xff1f; 2、那么如何查看运行级别呢?  3、那么我想临时切换运行级别? 4、那么我想修改配置文件中的运行级别呢? 1、有那7个运行级别&#xff1f; 0&#xff1a;停机状态。系统默认运行级别不能设置为0&#xff0c;否则系统不能正常启动&a…...

Linux期末总复习( 详解 )

文章目录 一、选择题二、填空题三、简答题四、操作题 一、选择题 1.在创建Linux分区时&#xff0c;一定要创建&#xff08; D &#xff09;两个分区 A. FAT/NTFS  B. FAT/SWAP  C. NTFS/SWAP  D.SWAP/根分区 2.在Red Hat Linux 9 中&#xff0c;系统默认的&#xf…...

【Linux系统化学习】进程等待

目录 进程等待 进程等待的必要性 进程等待的方法 wait方法 等待一个进程(阻塞等待&#xff09; waitpid方法 任意等待多个进程&#xff08;阻塞等待&#xff09; 父进程获取子进程的退出信息 非阻塞轮询等待 进程等待 进程等待的必要性 之前讲过&#xff0c;子进程退…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

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

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

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...