【嵌入式学习笔记-02】什么是库文件,静态库的制作和使用,动态库的制作和使用,动态库的动态加载

news2024/12/26 0:33:13

【嵌入式学习笔记-02】什么是库文件,静态库的制作和使用,动态库的制作和使用,动态库的动态加载

文章目录

  • 什么是库文件?
    • 编程模型的发展
    • 什么是库文件?
  • 静态库的制作和使用
  • 动态库的制作和使用
  • 动态库的动态加载

什么是库文件?

编程模型的发展

  • 单一模型:
    • 将程序中所有功能全部实现于一个单一的源文件内部。编译时间长,不易于维护和升级不易于协作开发。

image-20240103204445924

  • 分离模型
    • 将程序中的不同功能模块划分到不同的源文件中。缩短编译时间,易于维护和升级,易于协作开发。

image-20240103204611398

  • 对多个目标文件的管理比较麻烦
    • 将多个目标文件统一整理合成为一个文件便于使用和管理,于是就有了库文件。

image-20240103204735103

什么是库文件?

  • 为何要把一个程序分成多个源文件,并由每个源文件编译生成独立的目标文件?
    • 化整为零、易于维护、便于协作。
  • 为何要把多个目标文件合并成一个库文件?
    • 集零为整、方便使用、易于复用。
  • 可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
    • 库文件一般指计算机上的一类文件,分两种,一种是静态库,另一种是动态库。

静态库的制作和使用

  • 静态库的本质就是将多个目标文件打包成一个文件

  • 链接静态库的过程就是将库中被调用的代码复制到调用模块中

  • 静态库的拓展名是 .a 例: libxxx.a

    image-20240107221233826

  • 以构建数学库为例,静态库的构建顺序如下:

    • 1、编辑库的实现代码和接口声明:

      计算模块:calc.h、calc.c

      显示模块:show.h、show.c

      接口文件:math.h

    • 2、编译成目标文件

      gcc -c calc.c

      gcc -c show.c

    • 3、打包成静态库

      ar -r libmath.a calc.o show.o

  • ar 命令

    • ar[选项] <静态库文件> <目标文件列表>
      -r 将目标插入到静态库中,已存在则更新
      -q 将目标文件追加到静态库尾
      -d 从静态库中删除目标文件
      -t 列表显示静态库中的目标文件
      -x 将静态库展开为目标文件
  • 编辑库的使用代码

    • main.c
  • 编译并链接静态库

    • 直接链接静态库

      gcc main.c libmath.a

    • 用-l指定库名,用-L指定库路径

      gcc mian.c -lmath -L.

  • 用-l指定库名,用LIBRARY PATH环境变量指定库路径

    • export LIBRARY PATH=$LIBRARY_PATH:

    • gcc main.c -lmath

动态库的制作和使用

  • 动态库和静态库不同,链接动态库不需要将被调用的函数代码复制到包含调用代码的可执行文件中,相反链接器会在调用语句处嵌入一段指令,在该程序执行到这段指令时,会加载该动态库并寻找被调用函数的入口地址并执行之。
  • 如果动态库中的代码同时为多个进程所用,动态库在内存的实例仅需一份,为所有使用该库的进程所共享,因此动态库亦称共享库。
  • 动态库的拓展名是 .so 例如libxxx.so。
  • 链接动态库过程

image-20240110213858364

  • 以构建数学库为例,动态库的构建顺序如下:

    • 1、编辑库的实现代码和接口声明:
      计算模块: calc.h、calc.c
      显示模块: show.h、show.c
      接口文件: math.h
    • 2、编译成目标文件
      gcc -c -fpic calc.c
      gcc -c -fpic show.c
    • 3、打包成动态库
      gcc -shared calc.o show.o -o libmath.so
  • 编译链接也可以合并成一步完成。

    • gcc -shared -fpic calc.c show.c -o libmath.so
  • PIC(Position Independent Code,位置无关代码)。

    • 调用代码通过相对地址标识调用代码的位置,模块中的指令与该模块被加载到内存中的位置无关
  • -fPIC:大模式,生成代码比较大,运行速度比较慢,所有平台都支持

  • -fpic:小模式,生成代码比较小,运行速度比较快,仅部分平台支持

  • 编辑库的使用代码

    • main.c
  • 编译并链接动态库

    • 直接链接动态库

      `gcc main.c libmath.so

    • 用-l指定库名,用-L指定库路径

      gcc mian.c -lmath -L.

  • 用-l指定库名,用LIBRARY PATH环境变量指定库路径

    • export LIBRARY PATH=$LIBRARY_PATH:
    • gcc main.c -lmath
  • 运行时需要保证LD LIBRARY PATH环境变量中包含共享库所在的路径用以告知链接器在运行时链接动态。

    • export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
  • 在可执行程序的链接阶段,并不将所调用函数的二进制代码复制到可执行程序中,而只是将该函数在共享库中的地址嵌入到调用模块中,因此运行时需要依赖共享库。

动态库的动态加载

  • 在程序执行的过程中,开发人员可以动态加载共享库 (什么时候用什么时候加载),这样可以提高内存的利用效率。

  • 在程序中动态加载共享库需要调用一组特殊的函数,它们被声明于一个专门的头文件中,并在一个独立的库中予以实现。

  • 使用这组函数需要包含此头文件,并链接该库

    • #include<dlfcn.h>
    • -ldl
  • void* dlopen(char const* filename, int flag)

    • 功能:将共享库载入内存并获得其访问句柄

    • 参数:

      filename 动态库路径,若只给文件名不带目录,则根据LD LIBRARY PATH环境变量的值搜索动态库

      flag 加载方式,可取以下值
      RTLD LAZY - 延迟加载,使用动态库中的符号时才真的加载进内存。

      ​ RTLD NOW - 立即加载。

    • 返回值: 成功返回动态库的访问句柄,失败返回NULL。

    • 句柄: 句柄唯一地标识了系统内核所维护的共享库对象,将作为后续函数调用的参数

  • void* dlsym(void* handle, char const* symbol);

    • 功能:从已被加载的动态库中获取特定名称的符号地址

    • 参数: handle 动态库访问句柄

      ​ symbol 符号名

    • 返回值: 成功返回给定符号的地址,失败返回NULL。

    • 该函数所返回的指针为void*类型,需要造型为与实际目标类型相一致的指针,才能使用。

  • int dlclose(void* handle)

    • 功能:从内存中卸载动态库
    • 参数: handle 动态库句柄
    • 返回值: 返回值: 成功返回0,失败返回非0.
    • 所卸载的共享库未必会真的从内存中立即消失,因为其他程序可能还需要使用该库
    • 只有所有使用该库的程序都显示或隐式地卸载了该库,该库所占用的内存空间才会真正得到释放
    • 无论所卸载的共享库是否真正被释放,传递给dlclose函数的句柄都会在该函数成功返回后立即失效
  • char* dlerror(void)

    • 功能:获取在加载、使用和卸载共享库过程中所发生的错误
    • 返回值: 有错误则返回指向错误信息字符串的指针,否则返回NULL。
  • 辅助工具

    • 查看符号表: nm

      • 列出目标文件、可执行程序、静态库、或共享库中的符号
      • 例: nm libmath.a
    • 查看依赖: ldd

      • 查看可执行文件或者共享库所依赖的共享库
      • 例: ldd a.out

加载、使用和卸载共享库过程中所发生的错误

  • 返回值: 有错误则返回指向错误信息字符串的指针,否则返回NULL。

  • 辅助工具

    • 查看符号表: nm

      • 列出目标文件、可执行程序、静态库、或共享库中的符号
      • 例: nm libmath.a
    • 查看依赖: ldd

      • 查看可执行文件或者共享库所依赖的共享库
      • 例: ldd a.out

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

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

相关文章

只要3步,教你搞定网工领导满意的年终总结

你们好&#xff0c;我是老杨。 2024年的总结你们都写完了吗&#xff1f; 早的大厂都已经收了一波总结了&#xff0c;等着大年三十之前再搞个年终述职&#xff0c;这一年就算是齐活了。 老生常谈&#xff0c;但每年又不得不谈的总结&#xff0c;咱们今天就聊聊这个。 不管你是…

Mac版sublime快捷键大全

1 对应关系 标志 键名 ⌘ command ⇧ shift ↩ 回车 ↑ 上 ↓ 下 ⌃ control ⌥ option 红色标记的是常用的快捷键。 2 编辑 按键 功能 ⌘ X 剪切当前行 ⌥ 拖动鼠标 垂直选中 ⌘ ↩ 在当前行之后换行&#xff0c;无论鼠标在哪里 ⌘ ⇧ ↩ 再当前行之前换行&#xff0c…

【LV12 DAY20 RTC实验】

编程实现通过LED状态显示当前电压范围&#xff0c;并打印产生低压警报时的时间 注&#xff1a; 电压在1501mv~1800mv时&#xff0c;LED2、LED3、LED4、LED5点亮 电压在1001mv~1500mv时&#xff0c;LED2、LED3、LED4点亮 电压在501mv~1000mv时&#xff0c;LED2、LED3点亮 电压在…

常用界面设计组件 —— 字符串与输入输出组件(QT)

2.2 字符串与输入输出组件2.2.1 字符串与数值之间的转换2.2.2 QString的常用功能 2.2 字符串与输入输出组件 2.2.1 字符串与数值之间的转换 界面设计时使用最多的组件恐怕就是QLabel和 QLineEdit了&#xff0c;QLabel用于显示字符串&#xff0c;QLineEdit用于 显示和输入字符…

设计模式⑥ :访问数据结构

一、前言 有时候不想动脑子&#xff0c;就懒得看源码又不像浪费时间所以会看看书&#xff0c;但是又记不住&#xff0c;所以决定开始写"抄书"系列。本系列大部分内容都是来源于《 图解设计模式》&#xff08;【日】结城浩 著&#xff09;。该系列文章可随意转载。 …

为什么要找实习以及如何更好地度过实习期

前言 在职业发展的旅程中&#xff0c;实习是一个至关重要的阶段。不论是在大学生涯的尾声&#xff0c;还是在职场新人的起步阶段&#xff0c;寻找实习机会都是一项关键任务。然而&#xff0c;为什么要找实习&#xff1f;这个问题背后蕴含着更深层次的意义和价值。在这篇博客中…

Unity之物理系统

专栏的上一篇角色控制器控制角色移动跳崖&#xff0c;这一篇来说说Unity的物理系统。 本篇小编还要带大家做一个碰撞检测效果实例&#xff0c;先放效果图&#xff1a;流星撞击地面产生爆炸效果 一、Rigidbody 我们给胶囊添加了 Rigidbody 组件它才有的重力&#xff0c;我们来…

[Docker] Dockerfile

文章目录 什么是 Dockerfile&#xff1f;使用 Dockerfile 定制镜像开始构建镜像上下文路径 指令详解COPYADDCMDENTRYPOINTENVARGVOLUMEEXPOSEWORKDIRUSERHEALTHCHECKONBUILD 什么是 Dockerfile&#xff1f; Dockerfile 是一个用来构建镜像的文本文件&#xff0c;文本内容包含了…

Java SE入门及基础(15)

Java 中的标号&#xff08;标签 label&#xff09; 1. 语法规则 标号名称 : 循环结构 2. 作用 标号的作用就是给代码添加一个标记&#xff0c;方便后面使用。通常应用在循环结构中&#xff0c;与break 语句配合使用 3. 应用场景 有如下菜单&#xff1a; 实现其中返回主菜…

【UE Niagara 网格体粒子系列】03-大小变化的光圈

目录 效果 步骤 一、创建材质 二、创建渲染目标 三、使用蓝图将材质绘制到渲染目标 四、创建Niagara系统 4.1 设置网格体类型粒子 4.2 创建网格体粒子的材质 4.3 设置粒子初始颜色 4.4 设置粒子大小变化 效果 步骤 一、创建材质 1. 我们想要一个圆环的材质&…

数据管理-首选项

文章目录 1 概述2 什么是首选项3 首选项运作机制4 常用接口介绍常用接口使用前提保存数据&#xff08;put&#xff09;获取数据&#xff08;get&#xff09;是否包含指定的key&#xff08;has&#xff09;数据持久化&#xff08;flush&#xff09;删除数据&#xff08;delete&a…

LabVIEW模拟荧光显微管滑动实验

LabVIEW模拟荧光显微管滑动实验 在现代生物医学研究中&#xff0c;对微观生物过程的精准模拟和观察至关重要。本案例展示了如何利用LabVIEW软件和专业硬件平台&#xff0c;创新地模拟荧光显微管在滑动实验中的动态行为&#xff0c;这一过程不仅提升了实验效率&#xff0c;还为…

express服务连接mysql数据库

下载mysql2依赖包 npm i mysql2 创建mysql连接实例并暴露出去 const mysql require(mysql2)const mysqlMode mysql.createPool({host: 127.0.0.1, //服务端hostuser: root, //用户名称,mysql一般默认rootpassword: 123456, //密码database: sqlTest1, //数据库名字…

网络编程day2

TCP的基本通信 服务器端 #include <head.h> #define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.125.193" //服务器客户端int main(int argc, const char *argv[]) {//1、创建用于连接的套接字int sfd socket(AF_INET, …

Qt QTableWidget表格控件

文章目录 1 属性和方法1.1 行列数目和行表头和列表头1.2 单元格1.3 隔行交替背景色1.4 选择模式和选择行为1.5 设置样式表 2 实例2.1 布局2.2 代码实现 QTableWidget是Qt中的表格控件。 1 属性和方法 QTableWidget有很多属性和方法&#xff0c;完整的可查看帮助文档。 在窗口…

牛客周赛 Round 3 解题报告 | 珂学家 | 贪心思维场

前言 寒之不寒无水也&#xff0c;热之不热无火也。 整体评价 感觉比较简单&#xff0c;更加侧重于思维吧。和前几场的Round系列&#xff0c;风格不太一样。 A. 游游的7的倍数 因为连续7个数&#xff0c;比如有一个数是7的倍数 因此从个位数中着手添加&#xff0c;是最好的选…

Matter - 体验,灯泡(1)

一、前言 Matter&#xff08;当时称为 Project Connected Home over IP 或 Project CHIP&#xff09;于2019年12月11日首次宣布。当时&#xff0c;它是由苹果、谷歌、亚马逊和联发科技等公司共同发起的一个项目&#xff0c;目的是创建一个开放标准&#xff0c;提高智能家居设备…

【Linux】Git - 新手入门

文章目录 1. git 版本控制器 - 该如何理解&#xff1f;2. git / gitee / github 区别&#xff1f;3. Linux 中 git 的使用3.1 安装 git3.2 使用 github 新建远端仓库3.2.1 账号注册3.2.2 创建代码仓库3.2.3 克隆仓库到本地3.2.4 .gitignore 文件 3.3 使用 git 提交代码到 githu…

【方法】Excel表格如何“限制编辑区域”?

在制作Excel表格的时候&#xff0c;你是否遇到这些情况&#xff1f;有时候需要限定部分区域让他人协助填写&#xff0c;有时候会有很多数据或公式&#xff0c;要防止误改&#xff0c;否则会引起错误。要保护好这些区域&#xff0c;我们可以给Excel表格设置“限制编辑区域”。 …

震惊!你还搞不懂PMP中的合同类型?

PMP中的合同类型包括固定总价合同、总价加激励费用合同、总价加经济价格调整合同、成本加固定费用合同、成本加激励费用合同和成本加奖励费用合同等。 下面分别针对各类合同进行详细的说明&#xff1a; 固定总价合同&#xff08;FFP&#xff09;&#xff1a;是最常用的合同类型…