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.oar -rc $@ $^
%.o:%.cgcc -c $<
#Test:Add.o Div.o Mul.o Sub.o TestMain.o
#	gcc -o $@ $^.PHONY:output
output:mkdir -p mymath_lib/includemkdir -p mymath_lib/libcp -f *.h mymath_lib/includecp -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.ogcc -shared -o $@ $^
%.o:%.cgcc -fPIC -c $<.PHONY:output
output:mkdir -p mymath_lib/includemkdir -p mymath_lib/libcp -f *.h mymath_lib/includecp -f *.so mymath_lib/lib.PHONY:clean
clean:rm -rf *.o *.so mymath_lib

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

使用

在这里插入图片描述

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

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

相关文章

SkyEye:助力飞行器状态控制系统仿真

飞行器与常见的航天器一样&#xff0c;属于安全关键领域的大型复杂设备&#xff0c;对安全性、可靠性有着极高的要求。为保证稳定飞行&#xff0c;需要对目标对象进行实时跟踪&#xff0c;通过发出正确的修正偏差指令来操纵飞行器改变飞行姿态&#xff0c;因此对飞行器状态控制…

2024-03-13 作业

网络编程&#xff1a; 1.思维导图&#xff1a; 2.上课写的代码&#xff1a; 2.1网络字节序与主机字节序转换 运行代码&#xff1a; #include <myhead.h> int main() {int num 0x12345678;short int value 0x1234;int num_n htonl(num);int value_n htons(value);…

ISIS单区域实验简述

ISIS 中间系统到中间系统&#xff0c;也是链路状态协议&#xff0c;工作在数据链路层&#xff0c;不依赖IP地址&#xff1b;与OSPF一样采用最短路径SPF算法&#xff0c;收敛速度快。 实验基础配置&#xff1a; r1: sys sysname r1 undo info enable int g0/0/0 ip add 12.1.1.1…

jenkins 使用k8s插件连接k8s集群

jenkins 安装k8s 插件 配置k8s节点 填写k8s 配置信息 生成秘钥 在服务器上面 查看地址 cat /root/..kube/config 查看秘钥 -----BEGIN CERTIFICATE----- MIIDITCCAgmgAwIBAgIIGOkRkIVlo74wDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE AxMKa3ViZXJuZXRlczAeFw0yNDAyMDgwNjAwMjdaFw…

王庆:当下股市过于悲观,A股、港股基本完成补跌和普跌过程,逆向布局时机已到

核心观点&#xff1a; 1、房地产对中国经济增长拖累最严重的时期正在过去...密切关注真正拐点的出现。 2、当前资本市场从价格表现上来讲&#xff0c;表现的远远超过了基本面所决定的悲观程度。 由于当前资本市场过于悲观&#xff0c;那么反过来就是孕育着机会。 3、我们判…

快速排序 刷题笔记

思路 分治双指针 在每个区间选定一个基准目标 两个指针从数组的两边向中间推进 使用 while循环判断 do {i;}while(q[i]<x); do{j--;}while(q[j]>x); 每次这样做完就会找到q[i]>x,,,,q[j]小于x 此时我们交换 q[i] ,q[j]于是小于x的数分到了小于x的一侧 大…

《详解:鸿蒙NEXT开发核心技术》

我们现在都知道鸿蒙作为一个国产的全栈自研系统&#xff0c;经过国家主推后。已经引起人们很大的关注&#xff0c;其中作为开发者来说&#xff1b;许多一线大厂已经与其华为鸿蒙展开原生应用的合作了&#xff0c;目前了解到已经有200家。而之后出现了很多的高薪鸿蒙开发岗位&am…

【数据库-黑马笔记】基础-SQL

本文参考b站黑马数据库视频,总结详细全面的笔记 ,可结合视频观看1~26集 MYSQL 的基础知识框架如下 目录 一、MYSQL概述 1、数据库相关概念 2、MYSQL的安装及启动 二、SQL 1、DDL【Data Defination】 2、DML【Data Manipulation】 ①、插入 ②、更新和删除 3、 DQL【Data…

Linux本地搭建FastDFS系统

文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx 2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.…

jenkins部署go应用 基于docker-compose

丢弃旧的的构建 github 拉取代码 指定go的编译版本 安装插件 拉取代码是排除指定的配置文件 比如 conf/config.yaml 文件 填写配置文件内容 比如测试环境一些主机信息 等 可以配置里面 构建的时候选择此文件替换开发提交的配置文件。。。。 编写docker-compose 文件 docker…

短视频解析接口分发系统

宝塔面板&#xff1a;Nginx系统 php7.2 Mysql 5.6-5.7 伪静态Thinkphp 上传文件直接访问域名安装即可 可以自备 听说后边要出saas去水印小程序 下载地址&#xff1a;https://pan.xunlei.com/s/VNskSEelfRVIzoSm5P5Rcw34A1?pwdqzhh# 接口演示&#xff1a; 前端演示…

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

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

2024-Android大厂(字节跳动,腾讯

PS&#xff1a;全文点击蓝色文字&#xff0c;即可跳转链接 【字节面试官&#xff1a;看了3000多份简历&#xff0c;面试1000场后&#xff0c;想给金九银十找工作的程序员几点建议附大厂真题面经】 本文主要介绍校招&#xff0c;上半年疫情原因真正面试的时间和机会也不多&#…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的零售柜商品检测软件(Python+PySide6界面+训练代码)

摘要&#xff1a;开发高效的零售柜商品识别系统对于智能零售领域的进步至关重要。本文深入介绍了如何运用深度学习技术开发此类系统&#xff0c;并分享了全套实现代码。系统采用了领先的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5进行了性能比较&#xff0c;呈现了诸如…

FDU 2021 | 二叉树关键节点的个数

文章目录 1. 题目描述2. 我的尝试 1. 题目描述 给定一颗二叉树&#xff0c;树的每个节点的值为一个正整数。如果从根节点到节点 N 的路径上不存在比节点 N 的值大的节点&#xff0c;那么节点 N 被认为是树上的关键节点。求树上所有的关键节点的个数。请写出程序&#xff0c;并…

最新CLion + STM32 + CubeMX 开发环境搭建

网上有不少相关教程&#xff0c;但都是基于老版本Clion&#xff0c;新版有一些改变&#xff0c;但整体是简单了。 PS&#xff1a;本教程基于CLion 2023.3.4 安装所需工具参考&#xff1a;Clion搭建stm32开发环境&#xff08;STM32F103C8T6&#xff09;&#xff0c;有这一篇就够…

今天做了两个工具

URL可用性检测 2.影视 第一个工具为第二个工具服务&#xff0c;一定程度上检测了搜集到视频解析接口是否可用。

前端开发小技巧 - 【Vue3 + TS】 - 在 TS + Vue3 中使用 Pinia,实现 Pinia 的持久化,优化Pinia(仓库统一管理)

前言 ts 中使用 pinia 和 Vue3 基本一致&#xff0c;唯一的不同点在于&#xff0c;需要根据接口文档给 state 标注类型&#xff0c;也要给 actions 标注类型&#xff1b;以下都是 组合式API 的写法&#xff0c;选项式API 的写法大家可以去官网看看&#xff1b; Pinia&#xff…

【Flutter 面试题】在Flutter中如何处理用户输入和手势操作?

【Flutter 面试题】在Flutter中如何处理用户输入和手势操作&#xff1f; 文章目录 写在前面解答补充说明完整代码示例运行结果详细说明 写在前面 &#x1f64b; 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff0c;GitChat专栏作者&#xff0c;阿里云社区专家…

gpt-4-all模型中转实现

最近才完成这个功能&#xff0c;相信知道这个模型的人&#xff0c;应该已经熟悉了。这是我的中转&#xff1a;openai-api Chatbox配置如下&#xff1a; 模型测试&#xff1a; 1&#xff09;图片生成 2&#xff09;文件分析&#xff0c;链接读取&#xff1a;