Linux 动态库和静态库 【详解】

动静态库的基本原理

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

动静态库的本质是可执行程序的“半成品”。

对于文件变成可执行程序的过程:

  1. 预处理: 完成头文件展开、去注释、宏替换、条件编译等,最终形成xxx.i文件。
  2. 编译: 完成词法分析、语法分析、语义分析、符号汇总等,检查无误后将代码翻译成汇编指令,最终形成xxx.s文件。
  3. 汇编: 将汇编指令转换成二进制指令,最终形成xxx.o文件。
  4. 链接: 将生成的各个xxx.o文件进行链接,最终形成可执行程序。

就像这样,test1.c、test2.c、test3.c、以及main.c形成可执行文件,我们需要先得到各个文件的目标文件test1.o、test2.o、test3.o以及main.o,然后再将这写目标文件链接起来,最终形成一个可执行程序。

在这里插入图片描述
而实际上,对于可能频繁用到的源文件,比如这里的test1.c、test2.c、test3.c,我们可以将它们的目标文件test1.o、test2.o、test3.oo进行打包,之后需要用到这四个目标文件时就可以之间链接这个包当中的目标文件了,而这个包实际上就可以称之为一个库。
在这里插入图片描述
实际上,所有库本质都是一堆目标文件(xxx.o)的集合,库的文件当中并不包含主函数而只是包含了大量的方法以供调用,所以说动静态库本质是可执行程序的“半成品”。

认识动静态库

在Linux运行:

#include <stdio.h>

int main()
{
	printf("hello world\n"); //库函数
	return 0;
}

这份代码通过printf输出hello world,是因为gcc编译器在生成可执行程序,将C标准库也链接进来了。

在Linux下,我们可以通过ldd 文件名来查看一个可执行程序所依赖的库文件。
在这里插入图片描述
这里可执行程序所依赖的libc.so.6实际上就是C动态库,当我们去掉一个动静态库的前缀lib,再去掉后缀.so或者.a及其后面的版本号,剩下的就是这个库的名字。

而gcc/g++编译器默认都是动态链接的,若想进行静态链接,可以携带一个-static选项。

动静态库各自的特征

静态库

静态库是程序在编译链接的时候把库的代码复制到可执行文件当中的,生成的可执行程序在运行的时候将不再需要静态库,因此使用静态库生成的可执行程序的大小一般比较大。

优点:

  • 使用静态库生成可执行程序后,该可执行程序就可以独自运行,不再需要库了。

缺点:

  • 使用静态库生成可执行程序会占用大量空间,特别是当有多个静态程序同时加载而这些静态程序使用的都是相同的库,这时在内存当中就会存在大量的重复代码。

动态库

动态库是程序在运行的时候才去链接相应的动态库代码的,多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。

在可执行文件开始运行前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接。

在这里插入图片描述
优点:

  • 节省磁盘空间,且多个用到相同动态库的程序同时运行时,库文件会通过进程地址空间进行共享,内存当中不会存在重复代码。

缺点:

  • 必须依赖动态库,否则无法运行。

静态库的打包与使用

为了更容易理解,下面演示动静态库的打包与使用时,都以下面的八个文件为例,其中四个源文件Add.c,Sub.c,Mul.c,Div.c四个头文件Add.h , Sub.h,Mul.h,Div.h。

为了便于观看,都放入到一个展示:

//Add.c
#include "Add.h"


int Add(int x,int y)
{
    return x + y;
}

//Add.h
#pragma once

#include <stdio.h>
extern int Add(int,int);

//Div.c
#include "Div.h"

int Div(int x,int y, int *code)
{
    *code = 0;
    if(y == 0) 
    {
        *code = -1;
        return -1;
    }
    return x / y;
}

//Div.h
#pragma once

#include <stdio.h>

extern int Div(int,int,int*);

//Mul.c
#include "Mul.h"

int Mul(int x,int y)
{
    return x * y;
}

//Mul.h
#pragma once

#include <stdio.h>

extern int Mul(int,int);

//Sub.c
#include "Sub.h"

int Sub(int x,int y)
{
    return x - y;
}

//Sub.h
#pragma once

#include <stdio.h>

extern int Sub(int,int);

在这里插入图片描述

打包

我们使用Makefile来进行打包操作

static-lib=libmymath.a

$(static-lib):Add.o Div.o Mul.o Sub.o
	ar -rc $@ $^
%.o:%.c
	gcc -c $<
#Test:Add.o Div.o Mul.o Sub.o TestMain.o
#	gcc -o $@ $^

.PHONY:output
output:
	mkdir -p mymath_lib/include
	mkdir -p mymath_lib/lib
	cp -f *.h mymath_lib/include
	cp -f *.a mymath_lib/lib

.PHONY:clean
clean:
	rm -rf *.o *.a mymath_lib

第一行是替换,$(static-lib)就相当于libmymath.a
在这里插入图片描述
在这里插入图片描述

output操作是为了封装:

在这里插入图片描述

使用

在这里插入图片描述
此时使用gcc编译main.c生成可执行程序时需要携带三个选项:

  • -I:指定头文件搜索路径。
  • -L:指定库文件搜索路径。
  • -l:指明需要链接库文件路径下的哪一个库。

说明一下:

  • 因为编译器不知道你所包含的头文件add.h在哪里,所以需要指定头文件的搜索路径。
  • 因为头文件add.h当中只有my_add函数的声明,并没有该函数的定义,所以还需要指定所要链接库文件的搜索路径。
  • 实际中,在库文件的lib目录下可能会有大量的库文件,因此我们需要指明需要链接库文件路径下的哪一个库。库文件名去掉前缀lib,再去掉后缀.so或者.a及其后面的版本号,剩下的就是这个库的名字。
  • -I,-L,-l这三个选项后面可以加空格,也可以不加空格。

动态库的打包与使用

打包

我们使用Makefile来进行打包操作

dy-lib=libmymath.so

$(dy-lib):Add.o Div.o Mul.o Sub.o
	gcc -shared -o $@ $^
%.o:%.c
	gcc -fPIC -c $<

.PHONY:output
output:
	mkdir -p mymath_lib/include
	mkdir -p mymath_lib/lib
	cp -f *.h mymath_lib/include
	cp -f *.so mymath_lib/lib

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

在这里插入图片描述
output操作同样是为了封装

使用

在这里插入图片描述

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

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

相关文章

解决ipconfig不是内部或外部命令,也不是可运行的程序或批处理文件

问题所示&#xff1a;ipconfig不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 解决办法如下: 1.右击此电脑&#xff0c;点击属性设置&#xff1a; 2.点击高级系统设置 3.点击进入环境变量 4.在系统变量中进行设置&#xff0c;双击PATH进行配置 5.点击新建&am…

yum安装mysql、数据库tab自动补全,快来浅了解下 ?

centos7上面没有mysql&#xff0c;它的数据库名字叫做mariadb [rootlocalhost ~]#yum install mariadb-server -y [rootlocalhost ~]#systemctl start mariadb.service [rootlocalhost ~]#systemctl stop firewalld [rootlocalhost ~]#setenforce 0 [rootlocalhost ~]#ss -na…

Kotlin:泛型

点击查看泛型中文文档 点击查看泛型英文文档 简介 与 Java 类似&#xff0c;Kotlin 中的类也可以有类型参数&#xff1a; class Box<T>(t: T) {var value t }一般来说&#xff0c;要创建这样类的实例&#xff0c;我们需要提供类型参数&#xff1a; val box: Box<…

SpringBoot项目中出现不同端口跨域问题,如何解决?

方法一&#xff1a;比较繁琐&#xff0c;适合少量Controller控制器类 方法二 &#xff1a;需要写一个全局的配置文件即可 在如图所示的common目录下新建一个CorsConfig的class文件 具体代码展示&#xff1a; import org.springframework.context.annotation.Bean; import o…

淘宝客必看:微信公众号如何快速接入抖音本地团购并提高CPS收益

抖音已经成为社交媒体新的流量高地&#xff0c;抖音团购完全复刻了美团的模式&#xff0c;外卖、到店、吃喝玩乐全覆盖。很多淘宝客一直在寻找通过微信公众号实现营销变现的有效途径&#xff1f;是否对于如何将抖音团购转变为自己的佣金收入感到困惑&#xff1f;微信公众号接入…

Eslint + Prettier 配置

setting.json {"eslint.autoFixOnSave": true, // 保存文件时自动修复可修复的问题"eslint.validate": [// 定义哪些文件类型应该由 ESLint 验证"javascript","javascriptreact","vue" // 如果你正在使用 Vue&#xff0c;确…

基于单片机的GPS定位信息显示系统

基于单片机的GPS定位信息显示系统 摘 要 在当今信息时代的发展中&#xff0c;GPS全球定位系统是一个重要的组成部分&#xff0c;其具有精度很高、应用广泛、性能强大的特点&#xff0c;因此在实际生活中GPS全球定位显示系统被广泛运用于各类领域当中。它也是至今为止最好的定…

HarmonyOS 发送系统通知 基础通知

harmonyos中 提供了 各种不同功能的通知 来满足我们不同的业务需求 本文呢 我们先来看 最基本的通知 它的场景和使用方式 最基本的 是 当应用被切入后台 而应用内部发生了一些变化 就可以用通知的方式 来提醒用户 就比如 我们微信 被切到了后台 而这时 别人发消息过来了 那么…

2014

1,写出计算Ack(m,n)的递归算法 #include<iostream> using namespace std; int A(int m,int n){if(m0){return n1;}else if(m>0&&n0){return A(m-1,1);}else{return A(m-1,A(m,n-1));} }int main(){int m,n;cout<<"please input two number"&l…

【深度学习笔记】7_7 AdaDelta算法

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 7.7 AdaDelta算法 除了RMSProp算法以外&#xff0c;另一个常用优化算法AdaDelta算法也针对AdaGrad算法在迭代后期可能较难找到有用解的…

分享一个国内可用的AIGC网站,PC/手机端通用|免费无限制,支持Claude3 Claude2

背景 AIGC作为一种基于人工智能技术的自然语言处理工具&#xff0c;近期的热度直接沸腾&#x1f30b;。 作为一个AI爱好者&#xff0c;翻遍了各大基于AIGC的网站&#xff0c;终于找到一个免费&#xff01;免登陆&#xff01;手机电脑通用&#xff01;国内可直接对话的AIGC&am…

Aigtek:衡量基准电压源的技术指标有哪些

基准电压源在电子领域中扮演着至关重要的角色&#xff0c;它为各种应用提供了稳定、可靠的电压。为了确保电路的准确性和可靠性&#xff0c;工程师需要关注和评估基准电压源的技术指标。衡量基准电压源的技术指标有很多&#xff0c;下面将详细介绍其中几个重要的指标。 首先是输…

全面解析unityplayer.dll丢失的5种解决方法,轻松搞定dll丢失

在使用Unity开发的游戏或应用过程中&#xff0c;如果发现系统提示“找不到unityplayer.dll”文件&#xff0c;可能会引发一系列的问题与不便。这将直接导致游戏或应用程序无法正常启动运行&#xff0c;因为unityplayer.dll是Unity引擎的核心组件之一&#xff0c;负责处理关键的…

基于Web的论文管理系统设计

目 录 目 录 III 摘 要 V 关键词 V Abstract VI Key Word VI 第一章 绪论 6 1.1系统设计背景 1 1.2系统设计目的与意义 1 1.3国内外现状 2 1.4本文结构 3 第二章 需求分析 3 2.1系统需求分析 4 2.2系统角色设计 4 第三章 系统开发技术 4 3.1 PHP语言简介和特点 5 3.2 Mysql数据…

免费视频背景素材下载

找免费视频素材、背景就上这6个网站&#xff0c;高质量&#xff0c;无版权可商用。 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库虽然是个设计素材网站&#xff0c;但除了设计类素材之外还有很多视频、音频、办公类等素材&#xff0c;视频素材就有上…

5款可以免费使用的 UI 设计软件

在我们分享五个有用的原型工具之前&#xff0c;完成原型并优化界面。这是 UI 设计师的任务。UI 设计软件对设计师来说非常重要。UI 设计工具的使用是否直接影响最终结果&#xff0c;然后有人会问&#xff1a;UI 界面设计用什么软件&#xff1f;一些 UI 设计师和对 UI 设计感兴趣…

使用Docker管理linux容器

文章目录 一、使用docker管理镜像 二、使用docker管理容器 一、使用docker管理镜像 1、安装操作系统&#xff0c;我安装的是centOS 7 &#xff0c;因为centos7有着非常丰富的软件仓库&#xff0c;方便后续安装与docker相关的软件。 2、初始化设置&#xff0c; 关闭防火墙 关闭…

反爬虫技术:如何保护你的网站数据安全

在数字化时代&#xff0c;数据的价值日益凸显&#xff0c;而爬虫技术则成为了获取这些数据的重要手段之一。然而&#xff0c;对于网站运营者来说&#xff0c;非法爬虫不仅会导致数据泄露&#xff0c;还可能给网站带来巨大的流量压力和安全隐患。因此&#xff0c;本文将探讨如何…

Windows kafka 简单集群搭建

Windows kafka 简单集群搭建 文章目录 Windows kafka 简单集群搭建1.环境说明2.Zookeeper集群搭建2.1 ZooKeeper下载2.2 ZooKeeper安装2.2.1 解压zookeeper-3.4.8.tar.gz2.2.2 进入conf目录下&#xff0c;复制zoo_sample.cfg为zoo.cfg2.2.3 修改zoo.cfg文件2.2.4 生成myid文件2…

《LeetCode热题100》笔记题解思路技巧优化_Part_1

《LeetCode热题100》笔记&题解&思路&技巧&优化_Part_1 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题哈希&#x1f7e2;1. 两数之和&#x1f7e1;2. 字母异位词…