【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.o
	gcc -shared -o $@ $^
%.o:%.c
	gcc -c -fPIC $<

.PHONY:clean
clean:
	rm -rf *.o libmyc.so 

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

打包为压缩包:

libmyc.a:mymath.o mystdio.o
	ar -rc $@ $^
	rm *.o
%.o:%.c
	gcc -c $<

libmyc.so:mymath.o mystdio.o
	gcc -shared -o $@ $^
%.o:%.c
	gcc -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/include
	mkdir -p mylib/lib
	cp -rf *.h mylib/include
	cp -rf *.so mylib/lib
	cp -rf *.a mylib/lib
	tar 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的编写,以及如何处理动态库的查找问题,例如通过修改环境变量、创建软链接或配置系统路径等方法。最后,文章深入探讨了动态库的加载机制,包括系统如何管理已加载的库和动态链接的细节,揭示了操作系统、编译器和计算机体系结构在地址空间管理中的协同工作。通过本文的阅读,读者应该能够更加深入地理解动静态库的工作原理,以及如何在实际开发中有效地应用它们。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Netty中的ByteBuf使用介绍

ByteBuf有三类&#xff1a; 堆缓存区&#xff1a;JVM堆内存分配直接缓冲区&#xff1a;有计算机内存分配&#xff0c;JVM只是保留分配内存的地址信息&#xff0c;相对于堆内存方式较为昂贵&#xff1b;复合缓冲区&#xff1a;复合缓冲区CompositeByteBuf&#xff0c;它为多个B…

6月26~28日,2024北京国际消防展即将开幕!

随着社会的快速发展&#xff0c;消防安全日益受到广大民众的高度关注。为了进一步推动消防科技的创新与发展&#xff0c;提升全民消防安全意识&#xff0c;2024年北京消防展将于6月26日在北京国家会议中心盛大开展。目前:观众预登记已全面启动&#xff0c;广大市民和业界人士可…

Skins

本主题解释如何将DevExpress主题/皮肤应用到应用程序中&#xff0c;如何允许用户在运行时在主题之间切换&#xff0c;如何自定义现有皮肤或创建自己的皮肤&#xff0c;等等。 WinForms订阅包括许多基本控件&#xff1a;按钮、复选框、表单、消息框、对话框、对话框等。 我们实现…

python面向过程与初始面向对象编程

让我们穿越到《龙珠》世界&#xff0c;一起揭开 面向对象编程 的神秘面纱吧。 面向过程编程与面向对象编程 天下第一武道会 选手登记 第 22 届天下第一武道会即将召开&#xff0c;各路武术高手齐聚一堂&#xff0c;其中最受瞩目的&#xff0c;当属卡卡罗特&#xff08;孙悟…

Docker高级篇之Docker搭建mysql主从复制架构

文章目录 1. 安装mysql主从复制2. 主从复制测试 1. 安装mysql主从复制 首先创建主节点 docker run -d -p 3308:3306 \ --privilegedtrue \ -v /Users/jackchai/Desktop/lottory_docker/learndocker/mymysql/master/log:/var/log/mysql \ -v /Users/jackchai/Desktop/lottory_…

dots_image 增强图像中的圆点特征

dots_image 增强图像中的圆点特征 1. dot_image 有什么用途&#xff1f;2. 点状字符的特征增强3. Halcon代码 1. dot_image 有什么用途&#xff1f; Enhance circular dots in an image. 这个算子可以增强图像中的圆点特征&#xff0c;例如下面的例子。 2. 点状字符的特征增强…

【数据结构与算法 | 二叉树篇】力扣101, 104, 111,LCR144

1. 力扣101 : 对称二叉树 (1). 题 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false…

知识图谱的应用---智慧政务

文章目录 智慧政务典型应用 智慧政务 智慧政务即通过“互联网政务服务”构建智慧型政府&#xff0c;利用云计算、移动物联网、人工智能、数据挖掘、知识管理等技术&#xff0c;提高政府在办公、监管、服务、决策中的智能水平&#xff0c;形成高效、敏捷、公开、便民的新型政府&…

微前端之旅:探索Qiankun的实践经验

theme: devui-blue 什么是微前端&#xff1f; 微前端是一种前端架构方法&#xff0c;它借鉴了微服务的架构理念&#xff0c;将一个庞大的前端应用拆分为多个独立灵活的小型应用&#xff0c;每个应用都可以独立开发、独立运行、独立部署&#xff0c;再将这些小型应用联合为一个完…

3D打印随形水路:模具水路的革命性技术

在快速发展的模具制造行业中&#xff0c;3D打印技术以其独特的优势正在引领一场技术革命。其中&#xff0c;3D打印随形水路技术&#xff0c;凭借其灵活性和定制化设计的能力&#xff0c;为模具带来了前所未有的变革。 模具3D打印随形水路技术&#xff0c;是一种利用3D打印技术制…

环 境 变 量

如果希望某一个文件在 CMD 窗口的任意路径下都可以打开&#xff0c;则需要将该文件的路径存放在环境变量中。 在 CMD 中运行该文件时&#xff0c;优先查看当前路径下的文件&#xff0c;如果没有找到&#xff0c;则进入环境变量中记录的路径下寻找该文件&#xff0c;如果能找到…

阿里通义千问,彻底爆了!(本地部署+实测)

点击“终码一生”&#xff0c;关注&#xff0c;置顶公众号 每日技术干货&#xff0c;第一时间送达&#xff01; 问大家一个问题&#xff1a;你是否想过在自己的电脑上部署一套大模型&#xff1f;并用自己的知识库训练他&#xff1f; 阿里通义千问今天发布了最新的开源大模型系…

灵动岛动效:打造沉浸式用户体验

灵动岛是专属于 iPhone 14 Pro 系列交互UI&#xff0c;通过通知消息的展示和状态的查看与硬件相结合&#xff0c;让 iPhone 14 Pro 系列的前置摄像头和传感器的“感叹号”&#xff0c;发生不同形状的变化。这样做的好处是让虚拟软件和硬件的交互变得更为流畅&#xff0c;以便让…

M1Pro 使用跳板机

Mac (M1 Pro) 通过Iterm2 使用跳板机 1、由于堡垒机&#xff08;跳板机&#xff09;不能支持mac系统终端工具&#xff0c;只支持xshell等win生态。所以我们需要先安装iterm2 装iterms教程 这里头对rz、sz的配置不详细。我们可以这样配置&#xff1a; where iterm2-send-zmod…

关闭文件及使用with语句

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 1 关闭文件 打开文件后&#xff0c;需要及时关闭&#xff0c;以免对文件造成不必要的破坏。关闭文件可以使用文件对象的close()方法实现。close()方…

网络安全实验BUAA-全套实验报告打包

下面是部分BUAA网络安全实验✅的实验内容 &#xff1a; 认识路由器、交换机。掌握路由器配置的基本指令。掌握正确配置路由器的方法&#xff0c;使网络正常工作。 本博客包括网络安全课程所有的实验报告&#xff1a;内容详细&#xff0c;一次下载打包 实验1-路由器配置实验2-AP…

Linux存储管理

简介 硬件上的存储设备目前有两类&#xff0c;通过磁头读写信息的机械硬盘和用主控芯片将信息写入晶体管的固态硬盘&#xff0c;硬盘调度算法等知识可以通过前面的操作系统设备管理文章学习&#xff0c;本章只介绍Linux中能对存储设备的操作。 为了让操作系统识别和管理物理磁…

SAP ERP系统主要模块简介

SAP系统通过提供一系列高度灵活的模块&#xff0c;满足企业在不同业务领域的需求。这些模块不仅功能齐全且相对独立&#xff0c;但它们之间又能紧密协作&#xff0c;共同构筑一个协同高效的工作环境。 财务会计&#xff08;FI&#xff09;模块 它涵盖了总账、应收账款、应付账…

React@16.x(21)渲染流程-更新

目录 1&#xff0c;更新的2种场景2&#xff0c;节点更新3&#xff0c;对比 diff 更新3.1&#xff0c;React 的假设3.1.2&#xff0c;key 2.1&#xff0c;找到了对比的目标2.1.1&#xff0c;节点类型一致1&#xff0c;空节点2&#xff0c;DOM节点3&#xff0c;文本节点4&#xf…

通俗易懂的解释保护性看跌期权和抛补看涨期权!

今天带你了解通俗易懂的解释保护性看跌期权和抛补看涨期权&#xff01;当涉及期权交易时&#xff0c;保护性看跌期权和抛补看涨期权是两种常见的策略&#xff0c;它们的目的都是为了在特定市场情况下对投资进行保护或增强收益。 保护性看跌期权 保护性看跌期权是一种风险管理策…