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

news2024/11/28 22:40:20

文章目录

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

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

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

相关文章

【栈】1106. 解析布尔表达式

本文涉及知识点 栈 LeetCode 1106. 解析布尔表达式 布尔表达式 是计算结果不是 true 就是 false 的表达式。有效的表达式需遵循以下约定&#xff1a; ‘t’&#xff0c;运算结果为 true ‘f’&#xff0c;运算结果为 false ‘!(subExpr)’&#xff0c;运算过程为对内部表达式…

2024年【R2移动式压力容器充装】考试技巧及R2移动式压力容器充装复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装考试技巧参考答案及R2移动式压力容器充装考试试题解析是安全生产模拟考试一点通题库老师及R2移动式压力容器充装操作证已考过的学员汇总&#xff0c;相对有效帮助R2移动式压力容器充装复审考试学…

ubuntu系统 kubeadm方式搭建k8s集群

服务器环境与要求&#xff1a; 三台服务器 k8s-master01 192.168.26.130 操作系统&#xff1a; Ubuntu20.04 k8s-woker01 192.168.26.140 操作系统&#xff1a; Ubuntu20.04 k8s-woker02 192.168.26.150 操作系统&#xff1a; Ubuntu20.04 最低配置&#xff1a;2…

【启程Golang之旅】协程和管道操作

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

【ARM Cache 与 MMU 系列文章 7.6 -- ARMv8 MMU 配置 寄存器使用介绍】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 MMU 转换控制寄存器 TCR_ELxTCR_ELx 概览TCR_ELx 寄存器字段详解TCR 使用示例Normal MemoryCacheableShareability MMU 内存属性寄存器 MAIR_ELxMAIR_ELx 寄存器结构内存属性字段Devic…

人工智能在【肿瘤生物标志物】领域的最新研究进展|顶刊速递·24-06-08

小罗碎碎念 本期文献速递的主题是——人工智能在“肿瘤生物标志物”领域的最新研究进展。 重点关注 今天推荐的6篇文献中&#xff0c;第二篇和第三篇是小罗最喜欢的&#xff0c;因为对于临床来说&#xff0c;比较具有实际意义&#xff0c;也和自己的想法很契合。 尤其是第三篇…

华安保险:核心系统分布式升级,提升保费规模处理能力2-3倍 | OceanBase企业案例

在3月20日的2024 OceanBase数据库城市行的活动中&#xff0c;安保险信息科技部总经理王在平发表了以“保险行业核心业务系统分布式架构实践”为主题的演讲。本文为该演讲的精彩回顾。 早在2019年&#xff0c;华安保险便开始与OceanBase接触&#xff0c;并着手进行数据库的升级…

uniapp自定义的下面导航

uniapp自定义的下面导航 看看效果图片吧 文章目录 uniapp自定义的下面导航 看看效果图片吧 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6aa0e964741d4dd3a58f4e86c4bf3247.png) 前言一、写组件、我这里就没有写组件了直接写了一个页面&#xff1f;总结 前言 在…

ubuntu使用docker安装openwrt

系统&#xff1a;ubuntu24.04 架构&#xff1a;x86 1. 安装docker 1.1 离线安装 docker下载地址 根据系统版本&#xff0c;依次下载最新的三个关于docker的软件包 container.io&#xff08;注意后缀版本顺序&#xff09;docker-ce-clidocker-ce 然后再ubuntu系统中依次按顺…

javaweb学习(day14-ThreadLocal文件上传下载)

一、线程数据共享和安全 -ThreadLocal 1 什么是 ThreadLocal ThreadLocal 的作用&#xff0c;可以实现在同一个线程数据共享, 从而解决多线程数据安全问题. ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!] ThreadLocal 可以像 Map 一样存取数…

量化交易:Miniqmt获取可转债数据和交易python代码

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 低风险资产除了国债外&#xff0c;还有可转债&#xff0c;兼容有高收益的股性和低风险的债性&#xff0c;号称“下有保底&#xff0c;上不封顶”。 &#x1f50d; 可转债&#xff1a;金融市场的双面娇娃 可转债&am…

web学习笔记(六十五)

目录 1. Hash模式和History模式 2. 导航守卫 3. 路由元信息 4.路由懒加载 1. Hash模式和History模式 Hash模式&#xff08;哈希模式&#xff09;和History模式&#xff08;历史模式&#xff09;是匹配路由的两种模式&#xff0c;一般默认配置Hash模式&#xff0c;可以在in…

软件架构x86 、 x86_64、 arm64、aarch64

看系统信息: 大多数Linux发行版都提供如 uname -a命令 arch命令用于显示当前主机的硬件架构类型。 例如 下面的是Kylin Linux Advanced Server for Kunpeng V10 操作系统 (鲲鹏处理器是华为在2019年1月向业界发布的高性能数据中心处理器 ) 下面这个是 ubuntu 18.04.6 …

【AI论文与新生技术】Follow-Your-Emoji:精细可控且富有表现力的自由式人像动画技术

我们提出了 Follow-Your-Emoji&#xff0c;这是一种基于扩散的肖像动画框架&#xff0c;它使用目标地标序列对参考肖像进行动画处理。肖像动画的主要挑战是保留参考肖像的身份并将目标表情转移到该肖像&#xff0c;同时保持时间一致性和保真度。为了应对这些挑战&#xff0c;Fo…

四、利用启发式算法进行特定数据集的残差网络结构搜索【框架+源码】

背景&#xff1a;工作之后干的事情跟算法关联甚少&#xff0c;整理下读书期间的负责和参与的work&#xff0c;再熟悉学习下。 边熟悉边整理喽~ CV Tradictional workCV AI based work机械臂视觉抓取项目机器学习全流程 Pipeline训练平台OCR生产线喷码识别三维重建(SfM)ROS机器人…

SpringBoot Elasticsearch06-以黑马商场为例-黑马程序员学习笔记

黑马商城作为一个电商项目&#xff0c;商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的&#xff0c;存在很多问题。 首先&#xff0c;查询效率较低。 由于数据库模糊查询不走索引&#xff0c;在数据量较大的时候&#xff0c;查询性能很…

学习笔记——路由网络基础——汇总静态路由

4、汇总静态路由 (1)定义 静态路由汇总&#xff1a;多条静态路由都使用相同的送出接口或下一跳 IP 地址。(将多条路由汇总成一条路由表示) (2)目的 1.减少路由条目数量&#xff0c;减小路由表&#xff0c;加快查表速度 2.增加网络稳定性 (3)路由黑洞以及路由环路的产生…

旧衣回收小程序开发,轻松回收旧衣物

随着环保理念的增强&#xff0c;回收市场得到了快速发展&#xff0c;吸引了不少年轻人进入到市场中创业。除了传统的废品回收外&#xff0c;旧衣回收也受到了大众的重视&#xff0c;市场规模迅速扩大&#xff0c;大众浪费的衣物也获得了归处。 目前旧衣回收的方式主要是线上与…

如何将HTTP升级成HTTPS?既简单又免费的方法!

在当今数字化时代&#xff0c;网络安全已成为用户和企业关注的焦点。HTTPS作为一种更加安全的网络通信协议&#xff0c;正逐渐取代传统的HTTP成为新的标准。对于许多网站管理员和内容创作者来说&#xff0c;如何免费升级到HTTPS是一个值得探讨的问题。本文将详细介绍一些免费的…

Flash均衡算法几个点

Flash均衡保存算法是一种用于调整更改数据时擦除Flash存储器区域大小的高效算法。 在Flash存储器中&#xff0c;写入新数据时需要先将原有数据所在的块进行擦除&#xff0c;然后再进行写入操作。由于Flash存储器的特性&#xff0c;擦除操作比写入操作要慢得多&#xff0c;而且…