【Linux】深入解析动静态库:原理、制作、使用与动态链接机制

文章目录

  • 前言:
  • 1. 什么是动静态库
  • 2. 动静态库的制作和使用
  • 3. 动态库的查找问题
  • 4. 理解动态库的加载
    • 4.1. 站在系统的角度理解
    • 4.2. 编址、可执行程序
    • 4.3. 动态库动态链接和加载问题
  • 总结:

前言:

在软件开发中,动静态库是两种重要的代码复用和模块化手段。静态库(.a)在程序编译时将库代码整合到可执行文件中,而动态库(.so)则在程序运行时才链接库代码,使得多个程序可以共享同一份库代码。这种机制不仅提高了开发效率,还节省了磁盘和内存空间。本文将深入探讨动静态库的概念、制作和使用,以及动态库的查找和加载机制,帮助读者更好地理解和应用动静态库。

1. 什么是动静态库

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

a. 用过库吗? 用过,语言给我们提供了大量的库来进行链接。
b. 动态库 & 静态库: 系统默认安装动态库,云服务器,静态库(C标准库)默认是没有安装的。
c. 默认编译程序,用的是动态链接的,如果要静态加上 -static
d. libXXX.so、libYYY.a , 库真实的名字:XXX、YYY

2. 动静态库的制作和使用

站在库制作者的角度:我只给你提供 .o , 在不提供源文件的情况下也能形成可执行程序。

为什么要有库:

  1. 提高开发效率
  2. 隐藏源代码

所有的 .o 文件用特定的方式,进行打包,形成一个文件
在这里插入图片描述

// main.c
#include "mymath.h"
#include "mystdio.h"
#include <stdio.h>int main()
{int res = myAdd(10, 20);printf("%d + %d = %d\n", 10, 20, res);myFILE* fp = my_fopen("log.txt", "w");if (fp == NULL) return 1;return 0;
}

在这里插入图片描述
打包:

  ar -rc libmyc.a  mymath.o mystdio.o
gcc main.c -lmyc -L .

在这里插入图片描述
-L . :如果不像让 gcc 在当前目录下找了,可以将头文件添加到系统默认的头文件和库目录下。

gcc -c src.c -> src.o
gcc -c -fPIC src.c
动态库打包,我们不需要其它工具
makefile 文件:

libmyc.so: mymath.o mystdio.ogcc -shared -o $@ $^
%.o:%.cgcc -c -fPIC $<.PHONY:clean
clean:rm -rf *.o libmyc.so 

编写库的人:未来要给别人(用库的人), 交付的是: 头文件+库文件

打包为压缩包:

libmyc.a:mymath.o mystdio.oar -rc $@ $^rm *.o
%.o:%.cgcc -c $<libmyc.so:mymath.o mystdio.ogcc -shared -o $@ $^
%.o:%.cgcc -c -fPIC $<
#mymath.o:mymath.c
#	gcc -c -fPIC $<
#mystdio.o:mystdio.c
#	gcc -c -fPIC $<.PHONY:clean
clean:rm -rf *.o libmyc.so *.a mylib mylib.tgz.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp -rf *.h mylib/includecp -rf *.so mylib/libcp -rf *.a mylib/libtar czf mylib.tgz mylib

以目录的形式组织起来:(告诉编译器头文件和库所在的文件位置)
在这里插入图片描述
在这里插入图片描述

3. 动态库的查找问题

  1. 库没有在当前路径下
  2. 库没有安装到系统中
  3. 就是在我设定的目录内部

我们告诉的仅仅是编译器文件所在路径,可执行程序并不知道

所谓的把库(其它软件)安装到系统中,本质就是把对应的文件,拷贝到指定的路径中。

对动态库
编译时的搜索路径 —— gcc
运行时的库搜索路径 —— OS
将库安装在系统中(/lib64),既可以支持编译,又可以支持运行。

解决找不到动态库的4种方案

  1. 直接将库进行安装(拷贝)到系统中(朴实无华)(官方的库推荐)
  2. 将不在系统路径下的库路径,添加到 LD_LIBRARY_PATH 中
  3. 通过软链接的方式 (自己写的库推荐)
sudo ln -s /home/qhd/...(绝对路径) /lib64/libmyc.so
  1. 系统的配置文件路径方案

编译器选择库的情况:

  • 如果我们同时提供动态库和静态库,gcc默认使用的时动态库。
  • 如果我们非要静态链接,我们必须使用 static 选项。
  • 如果我们只提供的静态库,那我们的可执行程序也是没有办法,只能对该库进行静态链接,但程序一定整体是静态链接的。
  • 如果我们只提供静态库,默认只能动态链接,非得静态链接,会发生链接报错。

4. 理解动态库的加载

4.1. 站在系统的角度理解

库默认就是一个磁盘 级别的文件
库函数调用,依旧在进程的地址空间种进行的。
动态库加载之后,会被映射到进程的共享区中。
本质:所有系统进程中公共的代码和数据,只需要存在一份!

问题:

  1. 谁来决定,哪些库加载了,哪些没有加载? OS会自动完成
  2. 系统中可以同时存在非常多的已经加载到内存的库呢? 是! 操作系统要不要管理呢? 要!(先描述(用结构体描述),再组织(用链表管理起来))
struct loadlib 
{char *libname;void *addr;uint64_t time;struct loadlib *next;//...
}

4.2. 编址、可执行程序

可执行程序本身是有自己的格式信息的。
如果我们的可执行程序,没有加载到内存中,我们的程序中有没有地址呢?本来就有地址。
其实我们可执行程序,在没有加载之前,也已经基本被按照类别(比如权限,访问属性等)已经可执行程序划分为各个区域了。
我们进程地址空间里面的很多地址数据,是从可执行程序中来的 。

绝对编址的方式 —— 平坦模式
相对地址(逻辑地址) —— 段地址 + 偏移量

操作系统和编译器也有关系? 虚拟地址空间本身不仅是 OS 要遵守,编译器编译的时候也要遵守。

4.3. 动态库动态链接和加载问题

  1. 一般程序的加载
    地址空间既然是一个数据结构对象,谁来用什么数据初始化呢?
    代码是 “数据” 吗? 是
    所谓的地址空间,本质是由操作系统 + 编译器 + 计算机体系结构(CPU) 三者共同配合完成的。
  2. 动态库
    库的数据和方法访问,都是可以通过库在地址空间(起始地址 + 我们程序内部的偏移量)

总结:

本文详细介绍了动静态库的概念、制作、使用以及动态库的查找和加载问题。通过对比静态库和动态库的特点,我们了解到静态库在编译时链接,而动态库则在运行时链接,这使得动态库在节省空间和提高代码复用方面具有优势。文章还介绍了如何制作和使用动静态库,包括编译器选项和Makefile的编写,以及如何处理动态库的查找问题,例如通过修改环境变量、创建软链接或配置系统路径等方法。最后,文章深入探讨了动态库的加载机制,包括系统如何管理已加载的库和动态链接的细节,揭示了操作系统、编译器和计算机体系结构在地址空间管理中的协同工作。通过本文的阅读,读者应该能够更加深入地理解动静态库的工作原理,以及如何在实际开发中有效地应用它们。

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

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

相关文章

11.盛水最多的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容器。 示例 1&a…

编写程序提示用户输入一个数目(例如:100)、年利率(例如:5)以及月份数(例如:6),然后显示给定月份后账户上的钱数。

(财务应用程序:复利值)假设你每月向银行账户存 100美元&#xff0c;年利率为5%&#xff0c;那么每 月利率是 0.05/12-0.00417。 第一个月之后&#xff0c;账户上的值就变成:100*(10.00417)100.417 第二个月之后&#xff0c;账户上的值就变成(100100.417)*(10.00417)-201.252 第…

算法金 | 不愧是腾讯,问基础巨细节 。。。

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 最近&#xff0c;有读者参加了腾讯算法岗位的面试&#xff0c;面试着重考察了基础知识&#xff0c;并且提问非常详细。 特别是关于Ada…

[UE 虚幻引擎] DTLoadFbx 运行时加载FBX本地模型插件说明

本插件可以在打包后运行时动态加载FBX模型。 新建一个Actor 并添加一个 DT Runtime Fbx Component。 然后直接调用组件的函数 LoadFile 加载显示模型&#xff08;注&#xff1a;不支持模型动画&#xff09; FilePath : 加载模型的绝对路径。 Create Collision : 是否创建碰撞…

使用python绘制桑基图

使用python绘制桑基图 桑基图效果代码 桑基图 桑基图&#xff08;Sankey Diagram&#xff09;是一种用来表示流动&#xff08;如能源、资金、材料等&#xff09;在不同实体之间转移的图表。 每个流的宽度与流量成正比&#xff0c;通常用于显示能量或成本流动的分布情况。 桑基…

C++的重载

重载关系 同一作用域中&#xff0c;函数名相同&#xff0c;参数表不同的函数只有同一作用域中的同名函数才涉及重载问题&#xff0c;不 同作用域中同名函数遵循标识符隐藏原则 #include <QtCore/QCoreApplication> #include <QList> #include <QDebug> #in…

Cloudpods 强大的多云管理平台部署

简介 Cloudpods 是一款简单、可靠的企业IaaS资源管理软件。帮助未云化企业全面云化IDC物理资源&#xff0c;提升企业IT管理效率。 Cloudpods 帮助客户在一个地方管理所有云计算资源。统一管理异构IT基础设施资源&#xff0c;极大简化多云架构复杂度和难度&#xff0c;帮助企业…

AI绘画教程分享:Stable Diffusion使用指南,12000+AI关键词大合集

01 首先下载好SD的安装包&#xff08;百度、B站、小红书等都可以找到资源&#xff09;&#xff0c;用启动器开始运行 02 从这里下载别人的模型套用&#xff0c;可以多多探索一下&#xff01;以下是各个模型的具体介绍&#xff1a; 03 这就是我们打开的初始界面&#xff0c;常…

CondaSSLError: OpenSSL appears to be unavailable on this machine.

conda create -n x1 python3.7报错 PS C:\Users\Richardo.M.Song\Desktop\lele_seg\x1> conda create -n x1 python3.7 Collecting package metadata (current_repodata.json): failed CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is requ…

Allure在jenkins中无法显示的问题

jenkins中使用allure生成报告需要注意工作环境和路径的配置 前提条件&#xff1a; jenkins容器中已安装jdk和allure jenkins中配置全局工具环境&#xff1a; 项目中配置allure路径&#xff1a; 路径来源&#xff1a; Path需要选择相对路径的allure-report、allure-results

第八篇——矢量化:象形文字和拼音文字是如何演化的?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 通过这篇看似在讲文字的演化过程&#xff0c;实际是在说人生应该如何走&a…

天才简史——Tamim Asfour与他的H²T实验室

一、Tamim Asfour介绍 Tamim Asfour为KIT人类学和机器人学研究所&#xff08;Institute for Anthropomatics and Robotics&#xff09;的全职教授&#xff0c;并担任高性能人形技术实验室 (High Performance Humanoid Technologies Lab&#xff0c;HT) 负责人。他目前的研究兴…

使用LabVIEW进行大数据数组操作的优化方法

针对大数据量数组操作&#xff0c;传统的内存处理方法可能导致内存不足。通过LabVIEW的图像批处理技术&#xff0c;可以有效地进行大数据数组操作&#xff0c;包括分块处理、并行处理和内存优化等。这种方法能显著提高处理效率和系统稳定性。 图像批处理的优势 内存优化&#…

vs2017中C2440错误:“初始化”:无法从const char[6]转换为char*问题解决

本文摘要&#xff1a;本文已解决 Python FileNotFoundError 的相关报错问题&#xff0c;并总结提出了几种可用解决方案。同时结合人工智能GPT排除可能得隐患及错误。 &#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领…

Mamba v2诞生:2 那些烧脑的矩阵们

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提…

【Unity Shader入门精要 第13章】使用深度和法线纹理(二)

1. 再谈运动模糊 之前的文章中曾经通过保存渲染结果进行叠加的方式实现过运动模糊效果&#xff0c;下面的例子我们通过深度纹理重建世界坐标的方式来实现运动模糊&#xff1a; 首先&#xff0c;基于深度纹理重建像素的世界坐标&#xff0c;原理在【Unity Shader入门精要 第13…

LAMPSECURITY: CTF4 靶机实战

信息收集&#xff1a; 存活扫描&#xff1a; 端口扫描&#xff1a; 服务扫描&#xff1a; web页面&#xff1a; blog页面发现注入点&#xff1a; sql注入&#xff1a; sqlmap一把梭&#xff1a; 多个参数记得打&#xff1a; 哦 ssh登录&#xff1a; 老版本的ssh&#xff0c;…

Redis高频面试基本问题整理

文章目录 1、Redis底层协议2、Redis的热Key问题如何解决3、Redis是单线程还是多线程4、 什么是脑裂问题&#xff1f;5、redis集群会有写操作丢失吗&#xff1f;6、什么是 Redis 的 Pipeline&#xff1f;它有哪些优点&#xff1f;7、redis主从复制、哨兵机制、集群的理解8、缓存…

浏览器中的disable cache对文件下载服务的影响

客户端缓存文件 对于HTTP的文件请求来说&#xff0c;为了保证请求的速度&#xff0c;会使用客户端缓存的机制。比如客户端向服务器端请求一个文件A.txt。服务器在接收到该请求之后会将A.txt文件发送给客户端。 其请求流程如下&#xff1a; 步骤1&#xff1a;客户端请求服务器…

告别鼠标:蓝牙无线安卓模拟鼠标,绘图板,手写板操作电脑PC端,卡卡罗特也说好,儿童节快乐

家人们&#xff0c;上链接了&#xff1a;https://download.csdn.net/download/jasonhongcn/89387887 横屏模式&#xff1a; 竖屏模式&#xff1a; 操作说明&#xff1a; 1. 手势滑动模拟鼠标移动 2. 界面如果有滚动条&#xff0c;右手指按紧&#xff0c;通过左手指移动实现…