Linux动态库与静态库

news2024/10/2 8:28:32

Linux动态库与静态库

文章目录

  • Linux动态库与静态库
    • 1.库的概念、种类与使用
    • 2.链接简述
      • 2.1 链接过程理解
      • 2.2 静态链接与动态链接概念
      • 2.3 静态链接与动态链接的例子
    • 3.动态库与静态库的生成方法
      • 3.1 静态库的生成
      • 3.2 静态库的打包
      • 3.2 静态库的使用
      • 3.3 动态库的生成
      • 3.4 动态库的打包
      • 3.5 动态库的使用

1.库的概念、种类与使用

库的概念:一组.o文件的集合,或者说.obj文件(windows下)的集合,也就是链接生成可执行文件时用到的文件

请添加图片描述

在我的理解里,库就是别人写的代码,比如库函数,第三方库,包括之后会用到的网络库,这些都是别人写的,我们只是拿过来使用而已

那为什么我们要使用别人的代码呢?

因为:为了开发效率和代码的健壮性

那我们要如何使用别人的库?

  • 借助库、开源代码、和网络。下面我们主要了解库的使用
  • 如果别人要用我们的功能,我们又不想给源码,就可以把源码打包成一个库给对方用

库的种类:

链接分为动态链接和静态链接,库分为动态库和静态库。静态链接是一个过程,这个过程中用到的库就是静态库,动态链接同理

使用三方库时的链接过程:
请添加图片描述


2.链接简述

2.1 链接过程理解

链接过程简单概括为地址和空间分配,符号解析和代码重定位

符号指的是变量,函数名等,符号解析则是将符号的定义和符号的引用建立联系

重定位我简单理解为可以准确的运行我们的程序,比如一个函数,我们可以精准的找到函数入口的地址并进行运行

符号解析后生成符号表,linux下查看符号表命令:readelf -s 文件名.o

请添加图片描述

代码的重定位:我们运行的指令都有其对应的地址,比如我们进入一个函数就是跳到一个表示函数入口的地址,代码变化指令也会跟着变化,地址自然就变化了,比如前面一开始有4条代码,修改后有5条,那对应的指令和地址可能都要发生变化,函数入口就变化了,此时的代码里重新计算地址的过程就叫做重定位。如果有多个模块,成千上万行代码,修改这个地址的工作就是庞大的,早期还是人工改,现在都交给链接器了


2.2 静态链接与动态链接概念

静态链接概念:

  • 静态链接:是指编译阶段把静态库的代码加入到可执行文件中,或者说把用到的函数的全部链接到可执行文件中(但是链接器是以文件为单位进行操作的,比如要用printf就得链接所有包含printf的文件)。这样生成的可执行文件不需要借助外部的库,生成后可以直接使用,这就是静态链接。缺点是文件比较大,每次更新都得重新编译,优点是运行较快
  • 简言之:把需要的代码和数据从库全拷贝到当前代码

动态链接概念:

  • 动态链接:是什么时候要用到库里的东西就什么时候去找,存的也只是索引和相关的部分信息,所以占用空间不大。好处是占用空间小,所有的程序可以共用同一个库,更新也比较方便,缺点就是比较慢。如果我们有及时上百个进程都用了同一个库,那相比静态链接就大大节省了空间
  • 简言之:动态库可以被多个进程共享,与进程地址空间里的共享区有关

2.3 静态链接与动态链接的例子

gcc -o 命令默认动态链接,加上-static选项就表示静态链接,可通过file命令查看链接属性

#include <stdio.h>
int main()
{
  int a=1;
  printf("%d\n",a);
  return 0;
}

请添加图片描述

ldd命令,查看程序或者库文件所依赖的共享库,即打印动态链接依赖的库列表

下图中:libc.so.6,把lib和so去掉,中间剩下的c就是库名,.so就表示动态库,.a表示静态库,.6是主版本号

请添加图片描述

对于静态链接与动态链接的总结:

  1. 静态链接会拷贝代码和数据,再将其链接进可执行文件,因为链接器的操作单元又是文件,所以静态的链接的文件一般都较大,优点是快(不用去库里找东西自然快),不需要依赖外部(库丢失了也能跑)。但是不好更新,每次更新都得重新编译,比如包含了这个库里的某个函数的文件就全得更新
  2. 动态链接就是啥时候要就啥时候找,链接器看到动态链接的符号也会去找,只不过不分配地址,重定位的操作等到了程序装载时才做。但因为是通过索引去找,所以多个进程可以共享一个库(库丢失就跑不了了),一些场景下可以大大节省空间资源,更新时也方便,只用编译相对应的模块

3.动态库与静态库的生成方法

下面的动静态库生成剖析通过下面四个函数来验证:

add.h

#pragma once 
int add(int x,int y);

add.c

#include"add.h"
int add(int x,int y)
{
  return x+y;
}

sub.h

#pragma once 
int sub(int x,int y);

sub.c

#include"sub.h"
int sub(int x,int y)
{
  return x-y;
}

3.1 静态库的生成

下面以一个例子说明生成静态库的操作,我们利用ar工具把两个C文件打包成一个静态库。静态库里放.o文件,可以做到不暴露源码,再建一个目录放头文件,告诉使用者里面有哪些方法可以用
请添加图片描述


3.2 静态库的打包

静态库的打包过程:

关于ar命令的补充:

ar命令是gnu的归档工具,常用于将目标文件打包为静态库,下面我们使用ar命令的-r选项和-c选项进行打包

  • -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件
  • -c(create):建立静态库文件
  • -t:列出静态库中的文件
  • -v(verbose):显示详细的信息

打包流程:

  1. 第一步:让所有源文件生成对应的目标文件,即gcc -c add.c -o add.o等操作
  2. 第二步:使用ar命令将所有目标文件打包为静态库,即ar -rc …等操作
  3. 第三步:将头文件和生成的静态库组织起来,即cp add.h sub.h …等操作
  4. 第四步(可有可无):编写Makefile后,只需一个make就能生成所有源文件对应的目标文件进而生成静态库

请添加图片描述

生成的静态库名为libmymath.a.1,后面的1表示版本号,建议我们自己打包库的时候去掉版本号,不然后面使用的时候会显示找不到库…(也不知道为啥会找不到,网上查阅资料后发现静态库一般都把版本号写在文件里,再通过strings+文件里添加字符串version来标识文件是哪个版本,也有利用命令行参数来打印版本号的)


3.2 静态库的使用

gcc -o main main.c  -I ./include -L ./lib -lmymath -static
//-I指定去哪找头文件,-L指定去哪找库文件,-l+库名表示去找哪个库
//因为默认路径的缘故,gcc编译C代码都不用加-I -L -l等选项

请添加图片描述


3.3 动态库的生成

多个进程可以共享一个多态库,如下图:

请添加图片描述

动态库上面提到是要的时候再去找,所以多个进程用动态库时用的都是同一份代码,合理的节省了资源

请添加图片描述

-fPIC作用于编译时期,产生与位置无关的代码,编译后的代码用的是相对地址

用相对地址的原因共享库加载进内存的位置是不确定的,如果不加-fPIC选项,可能生成带有绝对位置的代码,那链接器链接时可能就需要去重新定位各个符号的位置,那共享库的代码可能就发生了变化,我们的程序此时就要去维护这段发生了变化的代码,维护进行的操作就是拷贝一份,那动态链接的作用就不大了(动态链接本来是要用的时候直接用库里的,现在我程序自身要维护一份更改后的代码,显然是不合理的),所以与位置无关的代码其实就是使用了相对地址的代码,这么做与elf文件的格式有关(借助了elf文件里面的“段”)。可以简单理解为规定了一根线,关于地址的坐标都是相对于这根线的,不管我程序加载到内存的哪个位置,只要通过计算这根线到当前位置的距离就可以获取到(算出)正确的位置。真正清晰的理解需要了解elf文件的格式,编译原理、链接器的相关知识

请添加图片描述


3.4 动态库的打包

动态库的打包相对于静态库来说有一点点差别,但大致相同,我们还是利用上面的四个文件进行打包演示:

动态库的打包流程:

第一步:让所有源文件生成对应的目标文件

  • 此时用源文件生成目标文件时需要携带-fPIC选项

  • -fPIC(position independent code):产生位置无关码

请添加图片描述

说明一下:

  • -fPIC作用于编译阶段,告诉编译器产生与位置无关的代码,此时产生的代码中没有绝对地址,全部都使用相对地址,从而代码可以被加载器加载到内存的任意位置都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的
  • 如果不加-fPIC选项,则加载.so文件的代码段时,代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的拷贝,并且每个拷贝都不一样,取决于这个.so文件代码段和数据段内存映射的位置
  • 不加-fPIC编译出来的.so是要在加载时根据加载到的位置再次重定位的,因为它里面的代码BBS位置无关代码。如果该.so文件被多个应用程序共同使用,那么它们必须每个程序维护一份.so的代码副本(因为.so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)
  • 我们总是用-fPIC来生成.so,但从来不用-fPIC来生成.a。但是.so一样可以不用-fPIC选项进行编译,只是这样的.so必须要在加载到用户程序的地址空间时重定向所有表目

第二步:使用-shared选项将所有目标文件打包为动态库

  • 与生成静态库不同的是,生成动态库时我们不必使用ar命令,我们只需使用gcc的-shared选项即可
gcc -shared -o libcal.so add.o sub.o

请添加图片描述


第三步:将头文件和生成的动态库组织起来

  • 与生成静态库时一样,为了方便别人使用,在这里我们可以将add.hsub.h这两个头文件放到一个名为include的目录下,将生成的动态库文件libcal.so放到一个名为lib的目录下,然后将这两个目录都放到mlib下,此时就可以将mlib给别人使用了

请添加图片描述


第四步:使用Makefile

  • 当然,生成动态库也可以将上述所要执行的命令全部写到Makefile当中,后续当我们要生成动态库以及组织头文件和库文件时就可以一步到位了

请添加图片描述

  • 编写Makefile后,只需一个make就能生成所有源文件对应的目标文件进而生成动态库

请添加图片描述

  • 一个make output就能将头文件和动态库组织起来

请添加图片描述


3.5 动态库的使用

我们使用下面main.c的代码作为例子:

//main.c
#include <stdio.h>
#include"add.h"
#include"sub.h"
int main()
{
  int a=add(0,1);
  printf("%d\n",a);

  return 0;
}

请添加图片描述
请添加图片描述
请添加图片描述

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

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

相关文章

[附源码]JAVA毕业设计基于web的面向公众的食品安全知识系统(系统+LW)

[附源码]JAVA毕业设计基于web的面向公众的食品安全知识系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&…

设备发现:通向全面网络可见性的途径

想实现企业网络安全防护&#xff0c;它首先需要完全了解其网络中发生的所有事件。有了这种可见性&#xff0c;企业网络安全管理员可以分析用户在网络环境中进行了哪些危险的操作&#xff0c;并采取必要的应对措施来主动保护企业网络免受攻击。 日志取证 但是&#xff0c;如果攻…

Java 每日一练 (7)

Java每日一练(7) 单选 1. JAVA属于&#xff08; &#xff09;。   A 操作系统 B 办公软件 C 数据库系统 D 计算机语言 答案 &#xff1a; java 是属于一门语言&#xff0c;是 计算可以识别的语言&#xff0c; 所以 答案 D 2. 类声明中&#xff0c;声明抽象类的关键字是 ( …

9.HTTP协议

通信有三要素&#xff0c;分别是通信的主体(通信的双方是谁)&#xff0c;通信的内容&#xff0c;通信的方式(打电话&#xff0c;写信这种)| 通信协议是通信双方完成通信所必须遵守的规则和约定 网页内容叫做超文本(HyperText)&#xff0c;网页内容的传输协议叫做超文本传输协…

JDSU故障测试仪维修OTDR光时域反射仪维修MTS2000

应用范围&#xff1a;邮电通信工程与维护&#xff0c;有线电视工程与维护&#xff0c;光缆制造商&#xff0c;光纤综合布线系统。 功能特点&#xff1a; 结构紧凑&#xff0c;重量轻&#xff0c;高度集成 已经可以支持40多个应用模块 有IL/ORL、OTDR、PMD、CD 或WDM 插拔模…

忆享科技聚焦|数字经济、网络安全、5.5G、数字火炬手……热点资讯一览

“忆享聚焦”栏目第十期来啦&#xff01;本栏目汇集近期互联网最新资讯&#xff0c;聚焦前沿科技&#xff0c;关注行业发展动态&#xff0c;筛选高质量讯息&#xff0c;拓宽用户视野&#xff0c;让您以最低的时间成本获取最有价值的行业资讯。 目录 行业资讯 1. 工信部&#xf…

十三、Vue CLI(1)

本章概要 简介安装创建项目 vue create使用图形界面 在开发大型单页面应用时&#xff0c;需要考虑项目的组织结构、项目构建、部署、热加载、代码单元测试等多方面与核心业务逻辑无关的事情&#xff0c;对于项目中用到的构建工具、代码检查工具等还需要一遍一遍地重复配置。…

大数据技术——结合Flume官方理解常用组件

Flume的常用组件包括Event和Agent。Agent又包含了Source、Channel以及Sink&#xff0c;本片文章将从官方说明文档入手&#xff0c;详细描述各组件以及组件的属性和功能。 文章目录1 常用的Source类型描述1.1 Netcat Source1.2 Exec Source1.3 Spooling Directory Source1.4 Tai…

【SQL】redo log | undo log

【SQL】日志redo日志和undo日志REDO LOGredo的整体流程UNDO LOG小结redo日志和undo日志 REDO LOG 称为重做日志&#xff0c;提供再写入操作&#xff0c;恢复提交事务修改的页操作&#xff0c;用来保证事务的持久性。 事务提交后&#xff0c;刚写完缓冲池&#xff0c;数据库宕…

Linux 必知必会

一、Linux 简介 Linux 与 Windows 和 Mac OS 等系统一样&#xff0c;它也是一个操作系统&#xff0c;并且是一个开源的类 unix 操作系统。凭借着其免费、安全、高稳定性等特点&#xff0c;被广泛应用于服务器、嵌入式开发等领域&#xff0c;并且在服务器领域一枝独秀&#xff0…

docker-compose Install Prometheus

前言 Prometheus是一个开源的系统监控和报警系统,现在已经加入到CNCF基金会,成为继k8s之后第二个在CNCF托管的项目,在kubernetes容器管理系统中,通常会搭配prometheus进行监控,同时也支持多种exporter采集数据,还支持pushgateway进行数据上报,Prometheus性能足够支撑上…

蒙代尔-弗莱明模型

蒙代尔-弗莱明模型 – 潘登的宏观经济学笔记 文章目录蒙代尔-弗莱明模型 -- 潘登的宏观经济学笔记IS-LM-BP蒙代尔-弗莱明模型资本完全流动固定汇率制度浮动汇率制资本完全不流动固定汇率制浮动汇率制资本不完全流动(KA主导&#xff0c;BP斜率小)固定汇率制浮动汇率制资本不完全…

代码随想录刷题|买卖股票问题的总结

目录 总结 121.买卖股票的最佳时机 问题描述 特点分析 动态规划思路 122.买卖股票的最佳时机Ⅱ 问题描述 特点分析 动态规划思路 123.买卖股票的最佳时机III 问题描述 特点分析 动态规划思路 188.买卖股票的最佳时机IV 问题描述 特点分析 动态规划思路 309.最…

tictoc例子理解 16-18

tictoc16-18tictoc 16 全局信号signaltictoc 17 在仿真界面幕布上显示总条数信息tictoc 18tictoc 16 全局信号signal 前一步的主要问题是&#xff0c;如果我们想要更改所收集的统计信息&#xff0c;就必须修改模型的代码。统计计算深入到模型代码中&#xff0c;很难修改和理解…

大型扫码点餐小程序系统源码

1. 开发语言&#xff1a;JAVA 2. 数据库&#xff1a;MySQL 3. 原生小程序 4. Sass 模式 5. 带调试视频 6. 可付费调试服务 扫码点餐小程序管理端&#xff1a; 数据统计&#xff1a;今日订单、堂食、预约、外卖、储值 堂食订单&#xff1a;订单号、商家、门店、类型、会员、桌位…

Spring进阶(二十)之事件处理

目录 为什么需要使用事件这种模式 事件模式中的几个概念 使用事件模式实现上面用户注册的业务 事件对象 事件监听器 事件广播器 事件广播默认实现 自定义用户注册成功事件类 用户注册服务 下面我们使用spring来将上面的对象组装起来 测试用例模拟用户注册 添加注册…

第四十篇 Vue封装swiper组件(v-swiper指令) 3.0

在前面讲到 Vue组件的封装不知道还记不记得&#xff0c;这里就不在过多的赘述&#xff0c;这里附上链接跳转可以进行回顾翻阅&#xff0c;上一篇内容​​​​​​​讲到这个自定义的指令&#xff0c;也就是为这篇封装swiper组件使用指令做铺垫的&#xff0c;那么也一同附在这里…

电子电气架构设计之三电系统设计

文中缩略词参考 SSTS&#xff1a;Sub System Technical Specification&#xff0c;子系统功能规范 CTS&#xff1a;Component Technical Specification&#xff0c;部件功能规范 DCDC&#xff1a;Direct Current Direct Current Converter&#xff0c;直流转直流变换器 BMS&…

Postgresql源码(92)深入分析HOT更新

0 概述与总结 hot更新已经有几篇分析了&#xff0c;这里是最后一篇&#xff08;总结性的&#xff0c;前面的可以忽略&#xff09;。前面在看update代码时&#xff0c;大部分集中在heap_update上&#xff0c;没有涉及寻找HOT链的逻辑。本篇重点看HOT链是如何使用的。 &#xf…

[附源码]计算机毕业设计JAVA鑫地酒店酒水库存管理系统论文

[附源码]计算机毕业设计JAVA鑫地酒店酒水库存管理系统论文 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; …