[基础IO]动静态库{创建/使用/加载}

news2024/11/24 12:09:39

文章目录

  • 1.创建静态库
  • 2.使用静态库
  • 3.动态库

1.创建静态库

  1. 预备知识: gcc main.c mymath.c myprint.c -o my.exe / gcc main.o mymath.o myprint.o -o my.exe三个.c/.o文件可以编译成为可执行程序
    在这里插入图片描述
  2. 编写源文件与头文件[库的源文件没有main函数]
  3. 将所有的源文件编译生成.o文件。(只提供.h和.o,用户也可以编译运行。⇒ 太麻烦,易出错 丢失文件不好找)
  4. 将所有的.o文件归档生成静态库。ar -rc libname.a self1.o self2.o. : r: replace c: creat
  • ar: archive files: gnu归档工具,用于归档生成静态库
  1. 发布静态库:将头文件统一放在include文件夹下 库文件统一放在lib文件夹下 include和lib放在self下
    在这里插入图片描述

  2. 利用Makefile自动化生成发布静态库[发布版的库可以打包成压缩文件给other使用]
    在这里插入图片描述

2.使用静态库

前提: 用户文件夹下有main.c + 发布版的静态库

  1. 法一: 将头文件和库文件直接拷贝到系统的默认搜索路径下[将库拷贝到系统默认搜索路径下的操作⇒ 库的安装]
    gcc头文件的默认搜索路径:/usr/include
    gcc库文件的默认搜索路径:/lib64 或者 /usr/lib64
    sudo cp -rf self/include/* /usr/include/.
    sudo cp -rf self/lib/libself.a /lib64.
  • C语言默认搜索的库ls /lib64/libc.a
    法一下运行main.c: gcc main.c -o test -l self. -l: 指定所要链接的库
  1. 法二: 通过-I和-L选项指定头文件和库文件的所在路径 -l指明要链接的库
    在这里插入图片描述

3.动态库

预备知识

  1. 使用静态库 是把代码加载到我们要运行的可执行程序中
    使用动态库 是让我们的代码和库产生关联
  2. gcc -fPIC: 形成与位置无关的二进制.o文件
    静态库只能存在于我们程序地址空间的特定位置 — 绝对地址 — 与位置有关
    动态库在任何位置都能被加载 — 相对地址 — 与位置无关
    ==> 可在内存中的任意位置加载和执行的代码,不依赖于特定的内存地址。
    在这里插入图片描述
  3. readelf -S命令用于显示一个目标文件或者一个二进制可执行文件的节表(section header table)的内容。节表包含了目标文件中的不同节(sections)的详细信息,例如代码段、数据段、符号表等。
  4. ldd a.out命令用于显示一个可执行文件或者共享库文件所依赖的动态链接库(shared library)。该命令会列出执行文件使用的动态链接库及其相对路径
  5. gcc 默认使用动态库 没有动态库 也没办法
    只有静态库时 针对该库 进行静态链接 ⇒ 拷贝式链接 其余仍使用动态库
    带上-static选项 只能使用静态库 ⇒ 摒弃默认优先使用动态库的原则 ldd时: not a dynamic executable

创建动态库

  1. 编写源文件与头文件
  2. 将所有的源文件编译生成目标文件[生成动态库的目标文件要加-fPIC选项,生成与位置无关的目标文件]
  3. 将所有的目标文件归档生成动态库
  4. 打包发布动态库:为动态库创建目录,并将头文件和库文件分开存放。
  5. 自动化生成并发布动态库

在这里插入图片描述

动态库的加载 文字解释来源: 芥末虾动态库

在这里插入图片描述

  1. 动态库没有被合并到可执行程序中,动态库与可执行程序是被分批加载到物理内存中的。⇒ 动态库是一个独立的库文件 可以和可执行程序分批加载
  2. 动态库被进程首次调用时,动态库代码被动态库链接器加载到物理内存,通过页表建立与地址空间的映射关系。动态库的全局变量和函数都会被映射到地址空间的共享区。
  3. 动态库代码采用相对编址的方式,其全局变量和函数在编译和链接时分配到的地址是相对地址(相对库起始地址的偏移量)⇒ 动态库代码与位置无关,每次运行程序,运行不同的实例,都可能会被映射到不同的虚拟地址处。
  4. 库的运行时虚拟地址(变化的) = 库的起始虚拟地址(变化的) + 库的相对地址(编译链接时分配);
  5. 如果有多个进程同时调用了同一个动态库,该动态库只需要向内存加载一次。之后凡是调用该动态库的进程只需要计算运行时地址,建立页表映射关系即可。⇒ 动态库也被成为共享库。

静态库的加载

  1. 静态库代码会同程序代码合并在一起进行编译和编址形成可执行程序,程序运行时可执行程序被程序加载器加载到物理内存,并通过页表映射到进程地址空间,程序的代码会被映射到的代码区,全局变量会被映射到静态区。
  2. 静态库代码采用绝对编址的方式,其全局变量和函数的虚拟地址在编译和链接时就已经确定,这个地址是固定的线性地址,不管程序运行多少次,运行多少个实例,它的地址始终是确定的,而且是唯一的线性地址。

动态库的使用

  1. 法一: 将头文件和库文件直接拷贝到系统的默认搜索路径下[不推荐]
  2. 法二: 通过-I和-L选项指定头文件和库文件的所在路径 -l指明要链接的库
    在这里插入图片描述
    报错: 找不到动态库 ⇒ 动态链接器运行时链接库缓存中没有对应动态库的路径

不是已经指定库了吗?-l self

那是给gcc命令说的 运行加载时 需要告知OS加载器库的位置 与gcc无关

如何向动态链接器缓存中添加动态库路径?

  1. 将动态库拷贝到/lib64路径下或者在/lib64路径下创建动态库文件的软链接 加载器默认会在该路径下进行搜索[不推荐]ln -s 绝对路径 /lib64/linself.so
  2. 在环境变量LD_LIBRARY_PATH中添加动态库的所在路径,加载器也会在环境变量中的路径下搜索动态库。[只是修改了bash缓冲区中的内容。只在本次登录中有效]export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: 路径.
  3. 在bash的资源配置文件.bashrc/.bash_profile中,添加登录时导入LD_LIBRARY_PATH环境变量的操作**[不推荐]**
  4. 在/etc/ld.so.conf.d/目录下添加配置文件,永久性添加动态库的搜索路径。ldconfig(加载配置文件 当配置文件发生改变 使用此命令 更新缓存!)是一个用于配置动态链接器运行时的命令。它用于更新动态链接器的运行时链接库缓存,以便在程序运行时能够正确地找到和加载动态库。sudo vim /etc/ld.so.conf.d/selflib.conf 在selflib.conf中存入/home/lhr/linux/lib/uselib/librelease/lib

库存在的意义

  1. 使用者的角度:大大减少使用者的开发周期;提高软件本身的质量
  2. 开发者的角度:使合作开发简单;隐藏源码,提高代码安全性

动静态库总结

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

优缺点

静态链接的优点:

  1. 执行速度快:静态链接的程序在运行时不需要额外的时间来加载和链接库文件,因此执行速度比较快。
  2. 安全稳定:静态链接的程序不依赖于外部的动态链接库,因此在运行时可以更好地保持程序的稳定性和兼容性,不受外部环境的影响。
  3. 独立性高:静态链接将所有的代码和库文件都打包在一起,使得程序具有很高的独立性,可以在没有其他依赖的系统上运行。

静态链接的缺点:

  1. 占用空间大:静态链接将所有的库文件都打包在一起,因此占用的存储空间比较大。
  2. 更新困难:如果某个库文件发生了更新,需要重新进行静态链接,这样会导致重新编译整个程序,对于大型程序而言更新不方便。

动态链接的优点:

  1. 空间利用率高:动态链接共享库文件,多个程序可以同时使用一个库文件,减少了存储空间的占用。
  2. 更新方便:如果某个库文件发生了更新,只需要更新一次库文件即可,不需要重新编译所有使用该库文件的程序。

动态链接的缺点:

  1. 执行速度相对较慢:动态链接的程序在运行时需要加载和链接库文件,会增加一定的执行时间。
  2. 对外部环境依赖较高:动态链接的程序需要依赖外部的动态链接库文件,因此在不同的环境中可能会出现兼容性问题

有趣的库

每一个动态库被加载到内存,映射到进程的地址空间,映射的位置可能是不一样的但是因为库里面是相对地址,每一个函数定位采用的是偏移量的方式找的
换句话说,只要知道这个库的相对地址,库的起始地址+函数偏移量 = 就可以在自己的地址空间中访问库中的所有函数[有访问权限]

  1. ncurses库是一个用于终端控制和终端用户界面(TUI)开发的C库。它提供了一组函数和数据结构,允许开发人员在文本终端或虚拟终端上创建复杂的用户界面,包括窗口、标签、按钮、菜单等。通过使用ncurses库,可以在终端上创建基于文本的用户界面,实现像图形界面一样的用户交互。[字符的界面库]

  2. boost库是一个C++库集合,提供了许多高质量的、被广泛接受的C++库,旨在增强C++语言的功能和功能。boost库包含了众多的组件和模块,提供了字符串处理、容器、算法、并发编程、日期和时间处理、正则表达式、文件系统操作等功能。通过使用boost库,可以简化C++开发,提高代码的可读性和可维护性,同时提供了许多常用的功能模块,能够快速开发高效的C++应用程序。[准标准库]

两个库的主要区别在于应用场景和功能:ncurses库主要用于终端用户界面的开发,而boost库主要用于增强C++语言的功能和提供常用的功能模块。同时,ncurses库是C库,而boost库是C++库。

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

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

相关文章

电工需要掌握的电路

1、通用型变频器接线示意图 2、三线式运转控制台达正反转电路图 3、单相220V接线实物图、三相380V接线实物图 4、变频器操作面板功能介绍 5、风暖浴霸实物接线电路图 6、车辆出入门闸检测实物接线电路图 7、电位器实现两台变频器同步调频实物接线图 8、门禁系统是如何工作的实物…

解决zabbix图像中文乱码

使用zabbix查看监控图像信息,发现会有中文乱码现象。 解决方法如下: 1.拷贝windows文字文件到服务器上 C:\Windows\Fonts目录下拷贝自己需要的中文语言文件 2.修改配置文件 vim /usr/share/zabbix/include/defines.inc.php 81行 define(ZBX_GRAPH_F…

vue3接入微信扫码授权登录流程

一、概要 本篇主要介绍两点,相关文档请查阅微信开平台 准备工作 | 微信开放文档 微信开放平台的登录授权相关流程vue3如何接入微信开放平台的微信授权登录功能二、微信开放平台的登录授权相关流程 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应…

6个.NET开源且强大的快速开发框架(帮助你提高生产效率)

中台Admin(Admin.Core) 中台Admin(Admin.Core)是前后端分离权限管理系统,前端 UI 基于Vue3开发,后端 Api 基于.NET 8.0开发。支持多租户、接口权限、数据权限、动态 Api、任务调度、OSS 文件上传、滑块拼图…

格式化日期注解@JsonFormat的使用和TimeZone时区问题

JsonFormat的使用 目的 为了便于date类型字段的序列化和反序列化,需要在数据结构的Date、Timestamp、DateTime类型的字段上用JsonFormat注解进行注解 使用 JsonFormat注解是一个时间格式化注解,比如我们存储在mysql中的数据是date类型的,当…

qml为程序设置图标(100%成功!3步搞定!)

步骤1 打开 CMakeLists.txt 文件,在 main.cpp 这行代码下面,添加一句:icon.rc。 步骤2 此时 icon.rc 这个文件还不存在,我们需要在目录中新建一个 .txt 文件,然后把文件名和后缀名改为 icon.rc。 步骤3 在 Qt Creat…

华为通过流策略实现策略路由(重定向到不同的下一跳)

通过流策略实现策略路由(重定向到不同的下一跳) 组网图形 图1 配置策略路由组网图 策略路由简介配置注意事项组网需求配置思路操作步骤配置文件 策略路由简介 传统的路由转发原理是首先根据报文的目的地址查找路由表,然后进行报文转发。但…

父类之王“Object”类和内部类

👨‍💻作者简介:👨🏻‍🎓告别,今天 📔高质量专栏 :☕java趣味之旅 欢迎🙏点赞🗣️评论📥收藏💓关注 💖衷心的希…

DS:时间复杂度和空间复杂度

创作不易,感谢三连! 一、算法 1.1 什么是算法 算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。…

MongoDB复制集实战及原理分析

文章目录 MongoDB复制集复制集架构三节点复制集模式PSS模式(官方推荐模式)PSA模式 典型三节点复制集环境搭建复制集注意事项环境准备配置复制集复制集状态查询使用mtools创建复制集安全认证复制集连接方式 复制集成员角色属性一:Priority 0属…

【边缘服务】

目录 边缘服务是一种新兴的技术趋势边缘服务的应用领域非常广泛边缘服务的核心特点之一是分布式部署另一个核心特点是低延迟边缘服务还可以提供更好的安全性和隐私保护总的来说 边缘服务是一种新兴的技术趋势 它将计算、存储和网络资源推向网络边缘,以实现更低的延…

【大厂AI课学习笔记】1.4 算法的进步(4)关于李飞飞团队的ImageNet

第一个图像数据库是ImageNet,由斯坦福大学的计算机科学家李飞飞推出。ImageNet是一个大型的可视化数据库,旨在推动计算机视觉领域的研究。这个数据库包含了数以百万计的手工标记的图像,涵盖了数千个不同的类别。 基于ImageNet数据库&#xf…

STM32--SPI通信协议(2)W25Q64简介

一、W25Q64简介 1、W25Qxx中的xx是不同的数字,表示了这个芯片不同的存储容量; 2、存储器分为易失性与非易失性,主要区别是存储的数据是否是掉电不丢失: 易失性存储器:SRAM、DRAM; 非易失性存储器&#xff…

RabbitMQ_00000

MQ的相关概念 RabbitMQ官网地址:https://www.rabbitmq.com RabbitMQ API地址:https://rabbitmq.github.io/rabbitmq-java-client/api/current/ 什么是MQ? MQ(message queue)本质是个队列,FIFO先入先出,只不过队列中…

opencv#41 轮廓检测

轮廓概念介绍 通常我们使用二值化的图像进行轮廓检测,对轮廓以外到内进行数字命名,如下图,最外面的轮廓命名为0,向内部进行扩展,遇到黑色白色相交区域,就是一个新的轮廓,然后依次对轮廓进行编号…

ShardingSphere 5.x 系列【5】Spring Boot 3.1 集成Sharding Sphere-JDBC并实现读写分离

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. 使用限制3. 案例演示3.…

教师考编制一年有几次报名机会

作为一名教师,考编制是职业生涯中重要的一环。但你知道吗?教师考编制的报名机会并不是固定的,而是因地区和考试类型而异。那么,教师考编制一年到底有几次报名机会呢? 目前,教师考编制主要有两种类型&#…

瑞_数据结构与算法_B树

文章目录 1 什么是B树1.1 B树的背景1.2 B 的含义1.3 B-树的度和阶1.4 B-树的特性1.5 B-树演变过程示例 2 B-树的Java实现2.1 B树节点类Node 🙊前言:本文章为瑞_系列专栏之《数据结构与算法》的B树篇。由于博主是从B站黑马程序员的《数据结构与算法》学习…

vue学习91-105

vue的基本认知p91 创建一个空仓库p93 vue 路由 vuex版本 2 3 3 3 4 4 npm的vuex装包npm install vuex --save vuex里有仓库,仓库放vuex核心代码,所有组件都能访问到 const store new Vuex.Store()//访问stored this.$store如何提供$访问vuex的数据p94 核心概念-…

SQL Server之DML触发器

一、如何创建一个触发器呢 触发器的定义语言如下: CREATE [ OR ALTER ] TRIGGER trigger_nameon {table_name | view_name}{for | After | Instead of }[ insert, update,delete ]assql_statement从这个定义语言我们可以知道如下信息: trigger_name&…