Linux笔记--静态库和动态库

        库是指在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为"库"文件;在链接步骤中,链接器将从库文件取得所需的代码,复制到生成的可执行文件中。

Linux中常见的库文件有两种,一种.a为后缀,为静态库,另一种以.so为后缀,为动态库

一、静态库

        可重定位目标文件以一种特定的方式打包成一个单独的文件,并且在链接生成可执行文件时,从这个单独的文件中“拷贝"它自己需要的内容到最终的可执行文件中。这个单独的文件,称为静态库。Linux中这类库的名字一般是libxxx.a。

1.创建步骤

将add.c sub.c创建成静态库文件:

  • 创建add.c sub.c
#add.c

int add (int a, int b) 
{
    return a + b;
}

#sub.c

int sub (int a, int b) 
{
    return a - b;
}
  • 对add.c sub.c编译成可重定位目标文件
gcc -c add.c -o add.o
gcc -c sub.c -o sub.o
  • 利用ar工具创建静态库: ar rcs lib 库名.a所有可重定位目标文件
#生成静态库
ar rcs libmath.a add.o sub.o 

2.静态库的使用

制作使用libmath.a静态库的程序

  • 创建main.c
#include<stdio.h>

int add(int a,int b);
int sub(int a,int b);

int main(int argc, char* argv[])
{
	int a=5,int b=3;
	printf("a+b=%d\n",add(a,b));
	printf("a-b=%d\n",sub(a,b));    
    return 0;
}
  • 编译main.c

编译时要将静态库libmath.a加上gcc选项:

  • l:指定库名(库的文件名为libxxx.a,库名为xxx)
  • L:指定库路径
  • static:使用静态链接
gcc -static main.c -l math -L ./
#注意:要先运行main.c后运行静态库文件

./a.out

特别注意,必须把-l math 放在后面。放在最后时它是这样的一个解析过程:

  • 链接器从左往右扫描可重定位目标文件和静态库
  • 扫描main.c时,发现两个未解析的符号add和sub,记住这两个未解析的符号
  • 扫描libmath.a,找到了前面未解析的符号,因此提取相关代码
  • 最终没有任何未解析的符号,编译链接完成

那如果将-l math放在前面,又是怎样的情况呢?

  • 链接器从左往右扫描可重定位目标文件和静态库
  • 扫描libmath.a,由于前面没有任何未解析的符号,因此不会提取任何代码
  • 扫描main.c,发现未解析的符号add和sub
  • 扫描结束,还有两个个未解析的符号,因此编译链接报错

生成可执行文件大小:

        生成的可执行文件大小为826k

        由于最终生成的可执行文件中已经包含了add和sub相关的二进制代码,因此这个可执行文件在一个没有libmath.a的Linux系统中也能正常运行。

二、动态库

        动态库和静态库类似,但是它并不在链接时将需要的二进制代码都“拷贝"到可执行文件中,而是仅仅“拷贝”一些重定位和符号表信息,这些信息可以在程序运行时完成真正的链接过程。Linux中这类库的名字一般是libxxx.so。(shared object)

1.创建步骤

//先编译成可重定位目标文件(生成与位置无关的代码-fPIC)
gcc -c add.c -o add.o -fPIC
gcc -c sub.c -o sub.o -fPIC
//使用gcc -shared 制作动态库
gcc -shared -o libmath.so add.o sub.o

-fPC作用:生成与位置无关的代码

2.动态库的使用

        通常我们编译的程序默认就是使用动态链接

gcc main.c -o main -l math -L ./

        通过动态库链接的程序只有8.5k.

        通过 ldd命令来观察可执行文件链接了哪些动态库:

        因为没有把 libmath.so 中的二进制代码“拷贝"可执行文件中,程序在其他没有上面的动态库时,将无法正常运行。

3.找不到动态库

        运行可以执行程序./main出错!!! ldd main --> "not found"

        链接器:工作于链接阶段,工作时需要-l和L

        动态链接器:工作于程序运行阶段,工作时需要提供动态库所在目录位置。

        原因:没有提供动态库的位置

解决方式:

  • 通过环境变量(临时生效): export LD_LIBRARY_PATH=动态库路径
  • 环境变量写入配置文件~/.bashrc(使用绝对路径),生效方法: .~/.bashrc或source ~/.bashrc 或 重启终端
  • 拷贝自定义动态库到lib(标准C库所在目录位置)(不推荐)

        【注】只是临时生效。关闭终端再重启时使用./main还会报错。如果想要一直生效需要写在配置文件中。

动态库绝对路径写到/etc/ld.so.conf配置文件中,生效方法: sudo ldconfig

三、静态库和动态库的区别

        静态库被使用目标代码最终和可执行文件在一起(它只会有自己用到的),而动态库与它相反,它的目标代码在运行加载时链接。正是由于这个区别,会导致下面所介绍的这些区别。

1.可执行文件大小

        静态链接的可执行文件要比动态链接的可执行文件要大得多,因为它将需要用到的代码从二进制文件中“拷贝”了一份,而动态库仅仅是复制了一些重定位和符号表信息。

2.扩展性与兼容性

        如果静态库中某个函数的实现变了,那么可执行文件必须重新编译,而对于动态链接生成的可执行文件,只需要更新动态库本身即可,不需要重新编译可执行文件。正因如此,使用动态库的程序方便升级和部署。

3.依赖原库文件

        静态链接的可执行文件不需要依赖其他的内容即可运行,而动态链接的可执行文件必须依赖动态库的存在。所以如果你在安装一些软件的时候,提示某个动态库不存在的时候也就不奇怪了。

即便如此,系统中一般存在一些大量公用的库,所以使用动态库并不会有什么问题。

4.加载速度

        由于静态库在链接时就和可执行文件在一块了,而动态库在加载或者运行时才链接,因此,对于同样的程序,静态链接的要比动态链接加载更快。所以选择静态库还是动态库是空间和时间的考量。但是通常来说,牺牲这点性能来换取程序在空间上的节省和部署的灵活性时值得的。

5.库的制作复杂度

        相对来讲,动态库的处理要比静态库要复杂,例如,如何在运行时确定地址?多个进程如何共享一个动态库?当然,这些我们不需要关注。另外动态库版本的管理也是一项技术活。

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

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

相关文章

【力扣白嫖日记】1045.买下所有产品的客户

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1045.买下所有产品的客户 表&#xff1a;Customer 列名类型customer_idintproduct_keyint 该表可能包含重复…

HashData的湖仓一体思考:Iceberg、Hudi特性讲解与支持方案

湖仓一体作为一种新兴的开放式数据管理架构&#xff0c;能够充分发挥数据湖的灵活性、生态丰富以及数据仓库的企业级数据分析能力&#xff0c;已经成为企业建设现代数据平台的热门选择。 在此前的直播中&#xff0c;我们分享了HashData湖仓一体方案架构设计与Hive数据同步。本…

2024金三银四--我们遇到的那些软件测试面试题【功能/接口/自动化/性能等等】

一、面试技巧题(主观题) 序号面试题1怎么能在技术没有那么合格的前提下给面试官留个好印象&#xff1f;2面试时&#xff0c;如何巧妙地避开不会的问题&#xff1f;面试遇到自己不会的问题如何机智的接话&#xff0c;化被动为主动&#xff1f;3对于了解程度的技能&#xff0c;被…

matlab 实现模糊C均值聚类

1. 原理 模糊c均值算法步骤&#xff1a; 1. 设定聚类数目c和加权指数b&#xff1a; 2. 初始化各个聚类中心m 3. 重复下面的运算&#xff0c;直到各个样本的隶属度值稳定&#xff1a;用当前的聚类中心根据下式计算隶属度函数&#xff1a; 用当前的隶属度函数按下式更新计算各…

fastApi笔记12-OAuth2 实现密码哈希与 Bearer JWT 令牌验证

JWT JWT(Json Web Token)是一种可以跨域的认证方案 jwt由三部分构成&#xff1a; 头部header&#xff1a;头部包含算法和token类型 核载payload&#xff1a;这部分用来保存自定义信息 签名signature&#xff1a;使用header和payload以及提供的秘钥&#xff0c;用header指定…

12c 32k strings新特性 varchar2/nvarchar2 32K

12c 32k strings新特性 varchar2/nvarchar2 32K 1、查看 SQL> show parameter MAX_STRING_SIZENAME TYPE VALUE ------------------------------------ ----------- ------------------------------ max_string_size …

Rust 开发的高性能 Python 包管理工具,可替换 pip、pip-tools 和 virtualenv

最近&#xff0c;我在 Python 潮流周刊 中分享了一个超级火爆的项目&#xff0c;这还不到一个月&#xff0c;它在 Github 上已经拿下了 8K star 的亮眼成绩&#xff0c;可见其受欢迎程度极高&#xff01;国内还未见有更多消息&#xff0c;我趁着周末把一篇官方博客翻译出来了&a…

12:Logstash|Web日志实时分析

Logstash|Web日志实时分析 logstashlogstash工作结构安装Logstash编写logstash配置文件步骤一:codec类插件插件帮助手册Logstash input插件步骤一:file模块插件filter grok插件Web日志实时分析部署beats与filebeat步骤一:filter grok模块插件logstash 一个数据采集、加工处…

基于巨控GRM561/562/563Y西门子1200PLC发邮件

巨控GRM560,GRM600系列同比之前的GRM530&#xff0c;除短信&#xff0c;微信&#xff0c;电话语音播报增加了邮件发送功能&#xff0c;简单介绍一下PLC发邮件。 1在博途中建立好DB块 2.打开GRMDEV6&#xff0c;新建工程&#xff0c;做好数据采集&#xff0c;这里以DB4.D0&#…

Day17:信息打点-APP资产知识产权应用监控静态提取动态抓包动态调试

目录 案例1&#xff1a;名称获取APP信息&#xff08;爱企查/小蓝本/七麦/点点&#xff09; 案例2&#xff1a;URL网站备案查APP 案例3&#xff1a;APP提取信息-静态分析 案例3&#xff1a;APP提取信息-动态抓包 案例4&#xff1a;APP提取信息-动态调试 思维导图 章节知识…

JavaWeb03-HTTP协议,Tomcat,Servlet

目录 一、HTTP协议 1.概述 2.特点 3.请求数据格式 &#xff08;1&#xff09;请求行 &#xff08;2&#xff09;请求头 &#xff08;3&#xff09;请求体 &#xff08;4&#xff09;常见请求头 &#xff08;5&#xff09;GET和POST请求区别 4.响应数据格式 &#xf…

Python一些可能用的到的函数系列125 FSM工具transitions

说明 首先FSM是一个很有用的工具&#xff0c;在程序设计中&#xff0c;某个对象会对应若干不同的状态&#xff0c;在这个状态下&#xff0c;同样的方法会有不一样的行为。 python有个transitions包可以做这个&#xff0c;过去一直不想用&#xff0c;主要是感觉有点鸡肋。 本质…

基于springboot+vue的个人博客系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Vue自定义商品发布组件

文章目录 一、代码展示二、代码解读三、结果展示 一、代码展示 <template><div><a-popover trigger"hover" :getPopupContainer"triggerNode > {return triggerNode.parentNode || document.body;}"><template #content><d…

Redis面试总结

概述 1. Redis是什么&#xff1f;简述它的优缺点&#xff1f; Redis本质上是一个Key-Value类型的内存数据库&#xff0c;很像Memcached&#xff0c;整个数据库加载在内存当中操作&#xff0c;定期通过异步操作把数据库中的数据flush到硬盘上进行保存。 因为是纯内存操作&…

[Angular 基础] - routing 路由(下)

[Angular 基础] - routing 路由(下) 之前部分 Angular 笔记&#xff1a; [Angular 基础] - 自定义指令&#xff0c;深入学习 directive [Angular 基础] - service 服务 [Angular 基础] - routing 路由(上) 使用 route 书接上回&#xff0c;继续折腾 routing 按照最初的 wi…

ffmpeg使用命令实现音视频分离

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、简单介绍二、具体操作三、验证1.源文件2.视频文件3.音频文件 四、补充总结 前言 有时候由于特殊需要可能需要将一个视频&#xff08;带音频&#xff09;的…

洛谷:P3068 [USACO13JAN] Party Invitations S(枚举、前缀和)

这题我们数据范围太大&#xff0c;用二维肯定是不行的&#xff0c;我们可以采用一维线性存储。 如题意&#xff0c;我们可以将每组奶牛编号都存在一维数组里面&#xff0c;只需记录每组的头尾指针就可以了。 如题中样例我们就可以存储成1 3 3 4 1 2 3 4 5 6 7 4 3 2 1 然后第…

docker部署aria2-pro

前言 我平时有一些下载视频和一些资源文件的需求&#xff0c;有时候需要离线下载&#xff0c;也要速度比较快的方式 之前我是用家里的玩客云绝育之后不再写盘当下载机用的&#xff0c;但是限制很多 我发现了aria2 这个下载器非常适合我&#xff0c;而有个大佬又在原来的基础…

基于 Vue3打造前台+中台通用提效解决方案(上)

基于 Vue3打造前台+中台通用提效解决方案 1、项目架构 本项目使用vite + vue3来实现前中台解决方案 2、为什么使用vite ? 因为,之前的项目一直都是使用webpack作为构建工具;vite出来这么久了,也没有用过;所以想在当前项目下进行使用; 2.1、为什么vite比webpack块? …
最新文章