Linux【动静态库】

news2024/12/28 18:54:02

目录

1.软硬链接

1.1软硬链接的语法 

1.2理解软硬链接

1.3目录文件的硬链接

1.4应用场景

1.5ACM时间

2.动静态库 

2.1认识库

3.制作静态库 

3.1静态库打包

3.2静态库的使用

4.制作动态库 

 4.1动态库打包

4.2动态库的链接使用 

 4.3动态库的链接原理

 总结:



前言:

在学习动静态库知识之前,我们先理解一下软硬链接的知识,本章节我们需要使用上一章节的inode知识,配合软硬链接制作动静态库。

1.软硬链接

1.1软硬链接的语法 

 语法:ln 【选项】【源文件】【新建链接】

 对文件进行软硬链接非常简单,只需要通过 ln -s 或 ln 对文件进行链接即可,生成的链接文件类型为 l(普通文件为 -,目录文件为 d

 对目录下的test2.txt进行软连接

 对目录下的file.txt进行硬链接

解除链接语法

unlink 【链接】

注意:

目录可以进行软连接但是无法进行硬链接,需要结合链接原理配合inode知识进行讲解,会在下面进行介绍。 

1.2理解软硬链接

inode和文件是一一对应的关系,但是从下图我们清晰的看到硬链接之后,两个文件的inode都是1706050 ,软连接之后,产生两个inode ;可以肯定的知道硬链接之后,没有创建新的文件,软连接是创建新的文件了。

软连接之后新的文件就会有新的属性和内容,内容里放的就是指向文件的路径。

硬链接则是在特定目录的数据块中新增,文件名和指向文件的inode的映射关系

 所以我们看到硬链接的连接数(引用计数为2)当我们删除硬链接或者文件的的时候,引用计数会减减,当引用计数为零的时候文件才会被删除。

文件系统中我们也知道,文件的部分属性在struct file中,但是大部分属性都在inode结构中包括引用计数

1.3目录文件的硬链接

不是说,文件不允许硬链接吗,为什么打开的目录我们能看到硬链接数为2?

这是因为新建目录之后,该目录下有两个隐藏文件 一个是.一个是..一个指向该目录一个指向上级目录,.这个文件就建立了和目录文件inode的映射关系。所以我们就看到硬链接数为2 

但是明明说好的目录是不可硬链接的,我们也测试了确实无法对目录文件做硬链接,显示not allowed,这个不冲突吗?需要解释一下,这个目录文件硬链接,是系统内部出厂就设置好的,是不允许用户手动建立的,为了避免用户误操作而导致目录环装问题;但是为了方便用户进行路径快速查找,对目标文件进行定位,内置了硬链接。

1.4应用场景

软链接可以当作快捷方式使用,比如快速运行一个藏的很深的可执行程序

而硬链接一是可以用来当作目录移动的工具,二是可以用来给重要的源文件起别名并使用,一旦发生删除等不可逆行为时,可以确保源文件的安全

1.5ACM时间

每一个文件都有三个时间:访问 Access、修改属性 Change、修改内容 Modify,简称为 ACM 时间

可以通过 stat 查看指定文件的 ACM 时间信息

注意:

Access 是高频操作,如果每次查看都更新的花,会导致 IO 效率变低,因此 实际变化取决于刷新策略:查看 N 后次刷新

 修改内容一定会导致属性时间被修改,但不一定会导致访问时间被修改,因为可以不打开文件,对文件进行操作。


2.动静态库 

2.1认识库

 我们在语言层面使用过很多库,常见的库文件:stdio.hstdlib.hstring.h 等

将链接好的文件进行打包就可以生成动静态库,动静态库在不同的操作系统规范也是不同的,我们常见的windos和linux区别如下:

  • Linux 中,.a 后缀为静态库,.so 后缀为动态库
  • Windows 中,.lib 后缀为静态库,.dll 后缀为动态库
  • 虽然不同环境下的后缀有所不同,但其工作原理是一致的

 我们可以查看一下我们系统上的库文件

find /usr/lib64/libc*

无论是 C语言 还是 C++,在编写程序时,一定离不开库文件,比如之前模拟实现的 FILE 类型,就位于 stdio.h 这个库中,动态库优势比静态库明显,因此在编译代码时,默认采用动态链接的方式,如果想指定为静态链接编译,只需要在 gcc/g++ 语句后面加上 -static 即可(前提是得有静态库)

关于动静态库的优缺点可以看看下面这个表格

 注意: 静态库是将所需要的函数代码拷贝到源文件中直接使用,而动态库是通过动态链接的方式,进行函数链接使用


3.制作静态库 

 通过小demo练习制作库

mymath.h

#pragma once

#include <stdio.h>

extern int myerrno;

int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);

mymath.c

#include "mymath.h"

int myerrno = 0;

int add(int x, int y)
{
    return x + y;
}
int sub(int x, int y)
{
    return x - y;
}
int mul(int x, int y)
{
    return x * y;
}
int div(int x, int y)
{
    if(y == 0){
        myerrno = 1;
        return -1;
    }
    return x / y;
}

main.c

#include "mymath.h"

int main()
{
    extern int myerrno;
 //   printf("1+1=%d\n", add(1,1));

    printf("10/0=%d, errno=%d\n", div(10, 0), myerrno);

    return 0;
}

3.1静态库打包

静态库的打包主要分为以下两步:

  1. 将源文件进行 预处理->编译->汇编,生成可链接的二进制 .o 文件
  2. 通过指令将 .o 文件打包为静态库

将文件编译为 .o 二进制文件

gcc -o mymath.c//-o 不带目标名直接生成同名文件.o

 将所有的 .o 文件打包为一个静态库(库名自定义)

其中的 mymath 为库名

ar -rc libmymath.a *.o

ar 是 GNU 提供的归档工具,常用来将目标文件打包为静态库
我们还可以使用 ar 反向查看静态库中的具体文件
ar -tv 静态库文件 

我们将.h头文件放进include目录下,将库文件放入mymathlib目录下,先进性目录创建

 

3.2静态库的使用

方法一:通过指定路径使用静态库

如果直接编译程序,会出现编译失败的情况,因为编译器不认识第三方库(需要提供第三方库的路径及库名)

第一方库:语言提供
第二方库:操作系统提供
第三方库:other 提供的库,比如当前我们直接打包的静态库

对于自己写的的第三库的使用,需要标注三个参数:

  1. -I 所需头文件的路径 需要将所需头文件的路径加上,此处为 .lib/include
  2. -L 所需库文件的路径 这里加的是库文件的路径,也为 ./lib/mymathlib
  3. -l 待链接静态库名 所需要链接的静态库名字,这里为 mymath

gcc -o mymath main.c -I./lib/include -L./lib/mymathlib -lmymath

为什么编译 C/C++ 代码时,不需要指定路径?

  • 因为这些库都是系统级的,gcc/g++ 默认找的就是 stdc/stdc++ 

方法二:将头文件和静态库文件安装至系统目录中

除了这种比较麻烦的指定路径编译外,我们还可以将头文件与动态库文件直接安装在系统目录中,直接使用,无需指定路径(需要指定静态库名)

所谓的安装软件,就是将自己的文件安装到系统目录下

sudo cp .lib/include/*.h /usr/include/
sudo cp .lib/mymathlib/*.a /lib64/

注意: 将自己写的文件安装到系统目录下是一件危险的事(导致系统环境被污染),用完后记得手动删除


4.制作动态库 

 4.1动态库打包

动态库不同于静态库,动态库中的函数代码不需要加载到源文件中,而是通过 与位置无关码 ,对指定函数进行链接使用

动态库的打包也同样分为两步:

  1. 编译源文件,生成二进制可链接文件,此时需要加上 -fPIC 与位置无关码
  2. 通过 gcc/g++ 直接目标程序(此时不需要使用 ar 归档工具)

将源文件编译为 .o 二进制文件,此时需要带上 fPIC 与位置无关码

小demo

mylog.h 

#pragma once

#include <stdio.h>


void Log(const char*);

mylog.c

#include "mylog.h"

void Log(const char*info)
{
    printf("Warning: %s\n", info);
}

myprint.h

#include "myprint.h"


void Print()
{
    printf("hello new world!\n");
    printf("hello new world!\n");
    printf("hello new world!\n");
    printf("hello new world!\n");
}

#pragma once

#include <stdio.h>


void Print();

mylog.c

#include "mylog.h"

void Log(const char*info)
{
    printf("Warning: %s\n", info);
}

通过这个小案例,把动静态库都制作了

gcc -c -fPIC *.c

将所有的 .o 文件打包为动态库(借助 gcc/g++

gcc -o libmycalc.so *.o -shared

 Makefile

dy-lib=libmymethod.so
static-lib=libmymath.a

.PHONY:all
all: $(dy-lib) $(static-lib)

$(static-lib):mymath.o
	ar -rc $@ $^
mymath.o:mymath.c
	gcc -c $^

$(dy-lib):mylog.o myprint.o
	gcc -shared -o $@ $^
mylog.o:mylog.c
	gcc -fPIC -c $^
myprint.o:myprint.c
	gcc -fPIC -c $^

.PHONY:clean
clean:
	rm -rf *.o *.a *.so mylib

.PHONY:output
output:
	mkdir -p mylib/include
	mkdir -p mylib/lib
	cp *.h mylib/include
	cp *.a mylib/lib
	cp *.so mylib/lib

4.2动态库的链接使用 

 像使用静态库一样使用动态库(指定路径及库名),编译成功,但运行失败!

为什么会出现这种问题?因为当前只告诉了编译器动态库的位置,没有告诉 加载器

通过 ldd 查看程序链接情况

 

运行时,OS 是如何链接动态库?

环境变量 LD_LIBRARY_PATH (默认没有这个环境变量),将第三方动态库路径添加至此环境变量中(临时方案)
sudo 在 /lib64/ 目录下建立动态库的软链接
更改配置文件 /etc/ld.so.conf.d 这个目录中都是各种动态库配置文件,创建文件 xx.conf 至目录中(文件中存储的是第三方动态库的路径)ldconfig 令配置文件生

方法一:通过环境变量解决

添加动态库路径至 LD_LIBRARY_PATH 环境变量中

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/cmx-108/lesson9/mylib/lib

环境变量 LD_LIBRARY_PATH 是程序在进行动态库查找时的默认搜索路径

注意: 更改环境变量只是临时方案,重新登录后会失效

方法二 复制到系统路径下,略

sudo ln -s /home/lesson9/mylib/lib/libmymethod.so /lib64/libmymethod.so

法三:更改配置文件中的信息

echo /home/cmx-108/lesson9/mylib/lib > cmx.conf
sudo mv cmx.conf /etc/ld.so.conf.d/
sudo ldconfig

 注意: 后两种方法都可以做到永久生效(因为存入了系统目录中),但在使用完后最好删除,避免污染系统环境

 4.3动态库的链接原理

程序在链接动态库函数时,是通过 动态库起始地址 + 所链接函数偏移量 的方式进行链接访问的,而这个偏移量就是 fPIC 与位置无关码

地址其实就两种:绝对地址和相对地址,静态链接时,将可链接的二进制文件加载至程序中,直接通过 绝对地址 进行链接,假设函数被调用了多次,就会导致代码冗余等问题;动态链接采用 相对地址 的方式进行链接,同一个函数的 动态库起始地址 + 所链接函数偏移量 值相同,代码只需要加载一份,并且可以任意位置进行函数调用(与位置无关)

动态库中所有地址都是偏移量,默认从 0 开始

只有当一个库被真正映射进地址空间后,它的起始地址才能真正确定

  • 链接库中的函数时,通过 动态库的起始地址 + 函数偏移量 的方式链接函数
  • 这种方法不论在什么位置,都可以随便链接函数(与位置无关)
  • 与位置无关码:动态库中地址,是偏移量

 总结:

关于系统对物理地址的管理,包括,进程如和找到page页。将页缓冲区到写到对应页框中,这个知识我还需要好好整理。和本章也不搭。动静态库的整理就到这了。

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

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

相关文章

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--强化学习等

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 分类: 大语言模型LLM视觉模型VLM扩散模型视觉…

Kotlin 基本语法5 继承,接口,枚举,密封

1.继承与重写的Open关键字 open class Product(val name:String ) {fun description() "Product: $name"open fun load() "Nothing .."}class LuxuryProduct:Product("Luxury"){//继承需要调用 父类的主构造函数override fun load(): String {…

热点参数流控(Sentinel)

热点参数流控 热点流控 资源必须使用注解 @SentinelResource编写接口 以及 热点参数流控处理器 /*** 热点流控 必须使用注解 @SentinelResource* @param id* @return*/ @RequestMapping("/getById/{id}") @SentinelResource(value = "getById", blockHand…

《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)

文章目录 3.1 编写 Dockerfile3.1.1 重点基础知识3.1.2 重点案例&#xff1a;创建简单 Python 应用的 Docker 镜像3.1.3 拓展案例 1&#xff1a;Dockerfile 优化3.1.4 拓展案例 2&#xff1a;多阶段构建 3.2 构建流程深入解析3.2.1 重点基础知识3.2.2 重点案例&#xff1a;构建…

外星文明会是朋友还是敌人?科学家用AI模拟揭示惊人答案!

引言&#xff1a;人类与外星文明的潜在互动 自古以来&#xff0c;人类就对外太空充满了好奇与向往&#xff0c;无数科幻作品中都描绘了人类与外星文明的潜在互动。然而&#xff0c;这些互动并非总是和平友好的&#xff0c;正如物理学家Stephen Hawking所警告的&#xff0c;盲目…

2024年全国乙卷高考文科数学备考:历年选择题真题练一练(2014~2023)

今天距离2024年高考还有三个多月的时间&#xff0c;今天我们来看一下2014~2023年全国乙卷高考文科数学的选择题&#xff0c;从过去十年的真题中随机抽取5道题&#xff0c;并且提供解析。后附六分成长独家制作的在线练习集&#xff0c;科学、高效地反复刷这些真题&#xff0c;吃…

小苯的IDE括号问题(CD) -----牛客小白月赛87(双链表)

C题&#xff1a;C-小苯的IDE括号问题&#xff08;easy&#xff09;_牛客小白月赛87 (nowcoder.com) D题&#xff1a; D-小苯的IDE括号问题&#xff08;hard&#xff09;_牛客小白月赛87 (nowcoder.com) C题代码&#xff1a; #include<bits/stdc.h>using namespace std…

HTTP攻击,该怎么防护

一般网络世界里为人们所熟知的DDoS攻击&#xff0c;多数是通过对带宽或网络计算资源的持续、大量消耗&#xff0c;最终导致目标网络与业务的瘫痪&#xff1b;这类DDOS攻击&#xff0c;工作在OSI模型的网络层与传输层&#xff0c;利用协议特点构造恶意的请求载荷来达成目标资源耗…

【Java程序设计】【C00286】基于Springboot的生鲜交易系统(有论文)

基于Springboot的生鲜交易系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的生鲜交易系统 本系统分为系统功能模块、管理员功能模块、用户功能模块以及商家功能模块。 系统功能模块&#xff1a;在系统首页可以…

信号系统之线性图像处理

1 卷积 图像卷积的工作原理与一维卷积相同。例如&#xff0c;图像可以被视为脉冲的总和&#xff0c;即缩放和移位的delta函数。同样&#xff0c;线性系统的特征在于它们如何响应脉冲。也就是说&#xff0c;通过它们的脉冲响应。系统的输出图像等于输入图像与系统脉冲响应的卷积…

125 Linux C++ 系统编程4 Linux 静态库制作,动态库制作,静态库和动态库对比。静态库运行时找不到库的bug fix

一 静态库 和动态库 对比 静态库的原理&#xff1a;假设我们有一个 静态库&#xff0c;大小为500M&#xff0c;这个静态库实现了一些打牌的逻辑算法&#xff0c;提供了一堆API&#xff0c;让开发者 可以轻松的实现 54张扑克牌的随机发牌&#xff0c;指定发牌等功能。 我们写了…

“点击查看显示全文”遇到的超链接默认访问的问题

今天在做一个例子&#xff0c;就是很常见的点击展开全文。 我觉得这是一个很简单的效果&#xff0c;也就几行代码的事&#xff0c;结果点击了以后立刻隐藏不见&#xff0c;控制台代码也不报错&#xff0c;耽误了我很长时间&#xff0c;最后才发现问题出在超链接身上。 “展开全…

搭建私有Git服务器:GitLab部署详解

引言&#xff1a; 为了方便团队协作和代码管理&#xff0c;许多组织选择搭建自己的私有Git服务器。GitLab是一个集成了Git版本控制、项目管理、代码审查等功能的开源平台&#xff0c;是搭建私有Git服务器的理想选择。 目录 引言&#xff1a; 一、准备工作 在开始部署GitLab之…

如何使用 NFTScan NFT API 在 Mantle 网络上开发 Web3 应用

Mantle Network 是建立在以太坊区块链之上的第 2 层扩展解决方案&#xff0c;采用了 Optimistic Rollups 技术&#xff0c;由 BitDAO 孵化&#xff0c;以提供比以太坊更快速和更经济的交易体验。由于 Mantle 基础链构建在 OP Stack 之上并与 EVM 兼容&#xff0c;因此以太坊网络…

使用向量数据库pinecone构建应用03:推荐系统 Recommender Systems

Building Applications with Vector Databases 下面是这门课的学习笔记&#xff1a;https://www.deeplearning.ai/short-courses/building-applications-vector-databases/ Learn to create six exciting applications of vector databases and implement them using Pinecon…

07 STL 简介

目录 什么是STLSTL的版本STL的六大组件STL的重要性如何学习STLSTL的缺陷 1. 什么是STL c标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构和算法的软件框架 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee在惠普实验室的…

postman测试上传文件、导出excel的方法

按照如下操作步骤执行就可以了&#xff1a; 1、PostMan测试接口实现上传文件 第一步&#xff1a; 打开postman&#xff0c;将上传方式改为POST&#xff0c;再点击下【Body】 第二步&#xff1a; 然后&#xff0c;我们点击里面的【form-data】选项(如图所示)。 第三步&#xff…

微服务Day6

文章目录 DSL查询文档RestClient查询文档快速入门 旅游案例 DSL查询文档 RestClient查询文档 快速入门 Testvoid testMatchAll() throws IOException {//1.准备RequestSearchRequest request new SearchRequest("hotel");//2.准备DSLrequest.source().query(QueryB…

医院信息系统(HIS):一文扫盲,算是所有信息系统里面复杂的

大家好&#xff0c;我是贝格前端工场&#xff0c;本期继续分享常见的B端管理系统&#xff0c;欢迎大家关注&#xff0c;如有B端写系统界面的设计和前端需求&#xff0c;可以联络我们。 一、什么是HIS系统 HIS系统&#xff08;Hospital Information System&#xff09;是医院信…

【探索Linux】—— 强大的命令行工具 P.23(线程池 —— 简单模拟)

阅读导航 引言一、线程池简单介绍二、Linux下线程池代码⭕Makefile文件⭕ . h 头文件✅Task.hpp✅thread.hpp✅threadPool.hpp ⭕ . cpp 文件✅testMain.cpp 三、线程池的优点温馨提示 引言 在Linux下&#xff0c;线程池是一种常见的并发编程模型&#xff0c;它能够有效地管理…