Linux 第二十六章

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

动静态库

在库的制作者角度

ldd

静态库的制作

动态库的制作

站在库的使用者角度

怎么使用自己静态库

怎么使用自己动态库

动态库加载 


动静态库

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

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

一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码

在库的制作者角度

库里是没有 main 函数的,我们也不能把 main 函数写入库中

ldd

ldd 命令是 Linux 系统中的一个工具,用于打印一个可执行文件或共享库所依赖的共享库信息。它的用法很简单,只需在终端中输入 ldd 命令,后跟待检查的可执行文件或共享库的路径,即可显示出该文件所依赖的共享库列表。


例如,要查看可执行文件 example 所依赖的共享库,可以执行以下命令:

ldd example
ldd 命令输出的信息包括:
依赖的共享库的路径
共享库的名称
共享库的版本信息
共享库的地址等信息

这些信息可以帮助你确定一个程序运行所需的共享库是否已经正确安装,并且可以帮助你解决程序运行时出现的共享库缺失或版本不匹配的问题。

需要注意的是,ldd 命令只能检查动态链接的共享库,对于静态链接的库则无法查看。

静态库的制作

静态库,本质是将库中的源代码直接翻译成为.o目标二进制文件,然后打包
1)将目标文件编译成 .o 文件

[BCH@hcss-ecs-6176 dc]$ gcc -c add.c sub.c mul.c div.c
[BCH@hcss-ecs-6176 dc]$ ll
总用量 52
-rw-rw-r-- 1 BCH BCH   55 1月  22 14:16 add.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 14:23 add.h
-rw-rw-r-- 1 BCH BCH 1240 1月  22 14:23 add.o
-rw-rw-r-- 1 BCH BCH   84 1月  22 14:16 div.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 14:23 div.h
-rw-rw-r-- 1 BCH BCH 1248 1月  22 14:23 div.o
-rw-rw-r-- 1 BCH BCH   55 1月  22 14:16 mul.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 14:23 mul.h
-rw-rw-r-- 1 BCH BCH 1240 1月  22 1:23 mul.o
-rw-rw-r-- 1 BCH BCH   55 1月  22 14:16 sub.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 14:23 sub.h
-rw-rw-r-- 1 BCH BCH 1240 1月  22 14:23 sub.o

2)使用 ar 命令将目标文件打包成静态库的.a文件:

[BCH@hcss-ecs-6176 dc]$ ar -rc libmymath.a add.o sub.o mul.o div.o
libmymath.a:是生成静态库的名字,在 linux 中,静态库的名字有前缀和后缀,
前缀必须lib开头,后缀必须.a结尾

动态库的制作

1)将目标文件编译成 .o 文件

[BCH@hcss-ecs-6176 dc1]$ gcc -fPIC -c add.c sub.c mul.c div.c
//在使用 -fPIC 选项编译代码时,编译器会生成与具体内存地址无关的代码,使得代码可以在不同的地址空间中加载和执行。这样,生成的可执行文件或共享库就更具通用性和灵活性。
[BCH@hcss-ecs-6176 dc1]$ ll
总用量 48
-rw-rw-r-- 1 BCH BCH   55 1月  22 15:31 add.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 15:31 add.h
-rw-rw-r-- 1 BCH BCH 1240 1月  22 15:32 add.o
-rw-rw-r-- 1 BCH BCH   84 1月  22 15:31 div.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 15:31 div.h
-rw-rw-r-- 1 BCH BCH 1248 1月  22 15:32 div.o
-rw-rw-r-- 1 BCH BCH   55 1月  22 15:31 mul.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 15:31 mul.h
-rw-rw-r-- 1 BCH BCH 1240 1月  22 15:32 mul.o
-rw-rw-r-- 1 BCH BCH   55 1月  22 15:31 sub.c
-rw-rw-r-- 1 BCH BCH   59 1月  22 15:31 sub.h
-rw-rw-r-- 1 BCH BCH 1240 1月  22 15:32 sub.o

2)以使用 GCC 将位置无关的目标文件链接到一个动态库中:

[BCH@hcss-ecs-6176 dc1]$ gcc -shared -o libmymath.so add.o sub.o mul.o div.o
libmymath.so:是生成动态库的名字,在 linux 中,动态库的名字有前缀和后缀,
前缀必须lib开头,后缀必须.so结尾

站在库的使用者角度

静态库,我们自己写的是第三方库,包含.h文件和.a(.o的集合)

gcc 默认动态链接的,如果你只提供.a,gcc 也没有办法,只能局部性的把你指定的.a,进行静态链接,其他库正常正常动态链接,如果gcc加上-static,就必须要.a

怎么使用自己静态库

为了使自己的静态库更加标准,我们得封装一下
1)我们得创建一个 mymath_lib 的目录,mymath_lib里面也包含两个目录,inlude 和 lib。include 目录里保存是头文件 ,lib里面保存的是.a文件

[BCH@hcss-ecs-6176 mymath_lib]$ tree .
.
├── include
│   ├── add.h
│   ├── div.h
│   ├── mul.h
│   └── sub.h
└── lib└── libmymath.a

2)使用我们的静态库
在 test.c中使用了add等函数,而 add 等函数在我们的静态库中

#include"add.h"
#include"sub.h"
#include"mul.h"
#include"div.h"
int main()
{int x=10;int y=20;printf("%d + %d = %d\n",x,y,add(x,y));printf("%d - %d = %d\n",x,y,sub(x,y));printf("%d * %d = %d\n",x,y,mul(x,y));printf("%d / %d = %d\n",x,y,div(x,y));
}

那我们怎么编译我们的 test.c文件呢

我们要把我们封装好的静态库mymath_lib放到和 test.c一个目录下[BCH@hcss-ecs-6176 dc]$ gcc test.c -I mymath_lib/include -l mymath -L mymath_lib/lib
-I mymath_lib/include:链接我们的头文件
-l mymath -L mymath_lib/lib:-l mymath链接我们的.a文件,-L mymath_lib/lib:指定链接.a文件的路径我们在mymath_lib/lib 目录下存的libmymath.a文件,我们使用的.a文件的文件名是 mymath

怎么使用自己动态库

为了使自己的动态库更加标准,我们得封装一下
1)我们得创建一个 mymath_lib 的目录,mymath_lib里面也包含两个目录,inlude 和 lib。include 目录里保存是头文件 ,lib里面保存的是.so文件

[BCH@hcss-ecs-6176 mymath_lib]$ tree .
.
├── include
│   ├── add.h
│   ├── div.h
│   ├── mul.h
│   └── sub.h
└── lib└── libmymath.so

2)使用我们的动态库
在 test.c中使用了add等函数,而 add 等函数在我们的动态库中

#include"add.h"
#include"sub.h"
#include"mul.h"
#include"div.h"
int main()
{int x=10;int y=20;printf("%d + %d = %d\n",x,y,add(x,y));printf("%d - %d = %d\n",x,y,sub(x,y));printf("%d * %d = %d\n",x,y,mul(x,y));printf("%d / %d = %d\n",x,y,div(x,y));
}

那我们怎么编译我们的 test.c文件呢

我们要把我们封装好的动态库mymath_lib放到和 test.c一个目录下
[BCH@hcss-ecs-6176 dc]$ gcc test.c -I mymath_lib/include -l mymath -L mymath_lib/lib-I mymath_lib/include:链接我们的头文件
-l mymath -L mymath_lib/lib:-l mymath链接我们的.so文件,-L mymath_lib/lib:指定链接.so文件的路径

第一种方法

接下来我们还需要把.h文件和.so文件放到 os 自带的库里
[BCH@hcss-ecs-6176 dc1]$ sudo cp mymath_lib/include/*.h /usr/include
[BCH@hcss-ecs-6176 dc1]$ sudo cp mymath_lib/lib/*.so /lib64
用 ldd 命令查看我们动态链接libmymath.so
[BCH@hcss-ecs-6176 dc1]$ ldd a.outlinux-vdso.so.1 =>  (0x00007ffd3d7a2000)libmymath.so => /lib64/libmymath.so (0x00007f547b350000)libc.so.6 => /lib64/libc.so.6 (0x00007f547af82000)/lib64/ld-linux-x86-64.so.2 (0x00007f547b552000)

第二种方法

在当目录下创建软连接
[BCH@hcss-ecs-6176 dc1]$ ls -li
总用量 16
2753548 -rwxrwxr-x 1 BCH BCH 8504 1月  22 16:10 a.out
2753538 lrwxrwxrwx 1 BCH BCH   27 1月  22 16:07 libmymath.so ->mymath_lib/lib/libmymath.so
2753540 drwxrwxr-x 4 BCH BCH 4096 1月  22 15:48 mymath_lib

第三种方法

使用环境变量的方式,让 os 找到动态库.so
[BCH@hcssecs6176dc1]$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/BCH/1_21/dc1/mymath_lib/lib
LD_LIBRARY_PATH环境变量
第四种方法
直接更改os 关于动态库的配置文件/etc/ld.so.conf.d/
1)添加一个.conf的文件
[BCH@hcss-ecs-6176 dc1]$ sudo touch /etc/ld.so.conf.d/math.conf
2)然后在.conf文件中添加一个.so的路径
[BCH@hcss-ecs-6176 dc1]$ cat /etc/ld.so.conf.d/math.conf
/home/BCH/1_21/dc1/mymath_lib/lib

同一组库,同时提供动态库和静态库,默认是使用动态库

动态库加载 

gcc -fPIC -c xxx.c//fPIC与位置无关码

1)程序加载的时候,库也要加载

2)程序没有被加载,程序内部有地址吗?
有的

变量名,函数名等,编译成为2 进制,全都都成了地址
在 C 语言中,变量和函数在编译期间会被编译成汇编代码,然后再由汇编器将汇编代码转换为二进制数据,最终生成可执行文件。在可执行文件中,变量和函数的实现代码已经被编译成二进制形式,而变量和函数名则以符号表的形式存储在可执行文件中。

当程序在运行时,操作系统会将可执行文件加载到内存中,并将其中的符号表信息加载到进程的符号表中。程序可以通过符号名称访问到对应的函数和变量的实现代码。

编译的时候,对代码进行编址,基本遵守虚拟地址空间那一套
虚拟地址空间,不仅仅是 OS 里面的概念。编译器编译的时候,也要按照这样的规则编译可执行程序,这样才能在加载的时候,进行从磁盘文件到内存,再进行映射


 3)绝对地址,相对地址
绝对地址:平坦模式,就和我们以前学的虚拟地址
相对地址:库函数的编址(与位置无关码有关)

动态链接链接的是动态库,而动态库中包含了大量的常用的功能接口指令代码

这种链接方式,是用于解决静态库存在的浪费内存和磁盘空间,以及模块更新困难等问题。

动态链接生成可执行程序,可执行程序中会记录自己依赖的库列表以及库中的函数地址信息,等到运行程序的时候,由操作系统将库加载到内存中(多个程序可以共享,不需要加载多份相同实例),然后根据库加载后的地址在对每个程序内部用到的库函数的地址进行偏移计算。

基于这么一种思想,动态链接具有以下优缺点:

更加节省内存并减少页面交换;

库文件与程序文件独立,只要输出接口不变,更换库文件不会对程序文件造成任何影响,因而极大地提高了可维护性和可扩展性;

不同编程语言编写的程序只要按照函数调用约定就可以调用同一个库函数;

适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。

运行时依赖,否则找不到库文件就会运行失败

运行加载速度相较静态库慢一些

需要对库版本之间的兼容性做出更多处理

 🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 

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

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

相关文章

【挑战30天首通《谷粒商城》】-【第一天】【10 番外篇】 解决docker 仓库无法访问 + MobaXterm连接VirtualBox虚拟机

文章目录 课程介绍 1、解决docker 仓库无法访问 2、 MobaXterm连接VirtualBox虚拟机 Stage 1:下载MobaXterm选择适合你的版本 Stage 2:vagrant ssh 连接,开启ssh访问 Stage 2-1:su获取root账号权限,输入密码(默认vagra…

Linux技能

文章目录 Linux2024心得优秀博客 Linux2024 心得 会一些基本的命令,解决生产的问题有时候会用的到 优秀博客 02、Linux相关工具及操作03、Linux实用指令 cat xxx | grep “xx xx” 这个应用在从大量的日志文件中找到报错的信息 04、Linux高级部分05、JavaEE定制…

【Web】CTFSHOW 七夕杯 题解

目录 web签到 easy_calc easy_cmd web签到 CTF中字符长度限制下的命令执行 rce(7字符5字符4字符)汇总_ctf中字符长度限制下的命令执行 5个字符-CSDN博客7长度限制直接梭了 也可以打临时文件RCE import requestsurl "http://4ae13f1e-8e42-4afa-a6a6-1076acd08211.c…

C++ Builder XE EnumWindowsProc遍历所有窗口的名称

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { // 这里可以添加你的处理逻辑 // 例如,将句柄添加到列表中或者其他操作 // 这里我们仅仅输出到调试窗口 OutputDebugString(L"枚举窗口句柄: "); char windowHandle[10];…

ICode国际青少年编程竞赛- Python-4级训练场-while语句入门

ICode国际青少年编程竞赛- Python-4级训练场-while语句入门 1、 while Flyer.disappear():wait() Dev.step(2)2、 Dev.step(1) while Flyer.disappear():wait() Dev.step(5)3、 while Flyer[0].disappear():wait() Dev.step(3) Dev.step(-1) while Flyer[0].disappear():…

准实时数仓搭建指南:以仓储式会员商超为模拟场景

在电商和新零售持续冲击传统零售商超的今天,仓储式会员店反而成功逃脱曾经的“水土不服”预测,业绩一路向好。与此同时,随着人工智能、大数据、智慧物流等技术的不断革新,零售批发的消费场景也进一步拓展,对数据分析的…

Linux部署安装

Linux部署安装 Linux中有两种软件安装包 一、源码包 软件的源代码是软件的原始数据,但是源代码不能直接在计算机中直接运行安装。 需要通过编译将源代码转换为计算机可以识别的机器语言,之后才可以进行安装。 源码包安装的方式可以在安装过程中发根据…

RERCS系统-WDA+BOPF框架实战例子 PART 1-新建List UIBB(列表组件)并分配Feeder Class和Node Element

需求背景: 已有的项目主数据功能,新增一个列表UIBB显示主数据额外的关联数据明细。 1、Fiori页面通过右键-技术帮助打开对应的组件配置; 2、双击对应的组件配置,调整对应的页面新建UIBB; 3、填写对应的UIBB属性字段&a…

doris 启动be报错

doris版本是1.2.4 java版本是:1.8 刚开始我以为是版本不兼容问题,后面发现思路错了,版本是兼容的,报以下错我的原因是操作系统没有达到安装要求 以下是博主在部署doris x64(avx2)版本中遇到的小bug 在大家使用doris的时候应该…

OpenNJet,够轻更强云原生应用引擎

前言: 在正式介绍OpenNJet之前,我们先来看看它的技术架构,如下图所示,OpenNJet正是NGINX的Pro版,在100%兼容NGINX基础上,新增了动态配置加载、主动式健康检测、集群高可用、声明式API等多种强大功能。 NGIN…

2024.05.10作业

TCP服务器 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QList> #include <QMessageBox> #include <QDebug>QT_BEGIN_NAMESPACE namespace Ui { class Widget; …

【神器来袭】快速解放双手,朋友圈自动转发工具,告别繁琐操作!

朋友圈作为一个重要的营销推广渠道&#xff0c;如果能实现自动转发&#xff0c;那对于很多企业或个人来说&#xff0c;是极好的。下面&#xff0c;就给大家分享一个实用且便捷的朋友圈运营工具——个微管理系统&#xff0c;让大家都能快速推广。 1、多账号登录&#xff0c;定时…

适用于 macOS 的最佳独立 HBO Max 客户端

适用于 macOS 的最佳独立 HBO Max 应用程序。不再在浏览器选项卡之间切换。只需直接从 Dock 启动 Clicker for HBO Max 即可开始狂欢。 HBO Max 客户端 Clicker for HBO Max 下载 Clicker for HBO Max mac版安装教程 软件下载完成后&#xff0c;双击pkg根据提示进行安装 Clic…

ssh远程免密登录

ssh远程连接分为五个阶段 版本号协商阶段密钥和算法协商阶段认证阶段会话请求阶段交互会话阶段 而上图的SessionKey即是在阶段2&#xff1a;密钥和算法协商阶段&#xff0c;服务器端和客户端利用DH交换&#xff08;Diffie-Hellman Exchange&#xff09;算法、主机密钥对等参数…

编译适配纯鸿蒙系统的ijkplayer中的ffmpeg库

目前bilibili官方的ijkplayer播放器&#xff0c;是只适配Android和IOS系统的。而华为接下来即将发布纯harmony系统&#xff0c;是否有基于harmony系统的ijkplayer可以使用呢&#xff1f; 鸿蒙版ijkplayer播放器是哪个&#xff0c;如何使用&#xff0c;这个问题&#xff0c;大家…

暴力法解决最近对问题和凸包问题-实现可视化

目录 最近对问题 凸包问题 最近对问题 顾名思义就是采用蛮力法求出所有点之间的距离&#xff0c;然后进行比较找出第一个最近对&#xff0c;一个一个进行比较。 大概思路就是如图&#xff08;每个圈代表一个数对&#xff09; 第一个和其他四个比较 第二个和其他三个比较 …

深入理解MQ消息队列的高可用与可靠性策略

在分布式系统架构中&#xff0c;消息队列&#xff08;Message Queue, MQ&#xff09;扮演着至关重要的角色&#xff0c;它负责解耦服务、异步处理以及提高系统的可扩展性。然而&#xff0c;消息的丢失是开发和运维过程中必须严格防范的风险&#xff0c;因为它直接影响到数据的一…

JavaScript 动态网页实例 —— DOM 中的事件处理

前言 DOM2事件模型规则描述了创建、捕获、控制与取消事件的标准方法,还描述了事件传播行为,也就是说,一个事件如何到达其目标,以及达到后将要发生的动作。在6中,由于没有提供对 DOM2事件模型的支持,因此,本章中涉及DOM2的代码只能在Netscape和Mozilla浏览器中正常运行。 D…

新版文件同步工具(Python编写,其中同时加入了多进程计算MD5、多线程复制大文件、多协程复制小文件、彩色输出消息、日志功能)

两个月前&#xff0c;接到一个粉丝的要求&#xff0c;说希望在我之前编写的一个python编写的文件同步脚本(Python编写的简易文件同步工具(已解决大文件同步时内存溢出问题)https://blog.csdn.net/donglxd/article/details/131225175)上加入多线程复制文件的功能&#xff0c;前段…

英语学习笔记8——What‘s your job?

What’s your job? 你是做什么工作的&#xff1f; 词汇 Vocabulary policeman 男警察 policewoman 女警察 police n. 警力 集合名词&#xff0c;永表复数 西方国家警察管的事很多。交警&#xff0c;刑警&#xff0c;武警一般不分开。 taxi driver 出租车司机 taxi / cab n.…