【详解】静态库和动态库的认识和使用【Linux】

静态库和动态库的认识和使用

  • 静态库和动态库的概述
  • 动静态库的实现
    • 静态库
    • 动态库
    • 库文件名称和引入库的名称

静态库和动态库的概述

  静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

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

  也就是对于静态库来说,程序会在链接阶段将库函数的代码毫无保留的链接到可执行文件中,这就使得我们可以看到静态库的底层代码细节,对于静态库提供者,这带来一些不安全的问题,同时对于静态库的使用者,会显得代码臃肿。
  对于动态库来说,动态库是在程序运行时才链接的,当程序需要调用某个库文件中的函数时,操作系统会在运行时自动加载该库文件,并将其中的函数(也就是返回函数的地址)链接到程序中,动态库的底层代码细节并不对外展示,从而实现代码的共享和复用。这样,多个程序可以共享同一个库文件,从而大大减少了程序的磁盘占用空间,同时也方便了库文件的维护和更新。


那动态库的代码也是需要加载进内存的,为什么会实现简洁呢?
  :简洁是对于程序来说的,使用静态库时,静态库的整个代码都在可执行程序里面,使用动态库时,动态库只有所需函数或变量的地址被包含在程序里面。

动态库的代码是什么时候加载进内存的?
:当程序第一次调用动态库中的函数或访问动态库中的变量时,操作系统的动态链接器(或称为动态加载器)会被触发。动态链接器会根据程序中的指令,从磁盘上读取对应的动态库文件,并将其加载到进程的内存空间中。


动态库的代码是什么时候卸载的?
  :动态库的卸载不是立即发生的,而是在满足一定条件时才会进行卸载。
  当一个程序使用完动态库后,如果其他程序或进程也在使用相同的动态库,那么动态库会继续留在内存中供其他程序使用,不会被立即卸载。这是因为动态库可以被多个程序共享,避免了重复加载和占用额外内存空间。
  只有在满足以下条件时,动态库才会被卸载:

  • 引用计数为零:当所有使用该动态库的程序或进程都结束了对动态库的使用,并且没有其他程序或进程在使用该动态库时,动态库的引用计数会变为零。这表示没有程序再需要该动态库,此时动态库可以被卸载。
  • 卸载策略:操作系统或动态链接器可能还会采用一些卸载策略来决定何时卸载动态库。这些策略可能考虑到资源利用率、性能等因素,以平衡系统的需求。
      需要注意的是,动态库的卸载是由操作系统或动态链接器自动管理的,程序本身无法直接控制动态库的卸载。程序只需要在使用完动态库后正确关闭句柄或释放相关资源,让引用计数递减,卸载过程由操作系统或动态链接器负责。

动静态库的实现

  我们基于下面这些代码来封装动静态库:

/add.h/int add(int a, int b);/add.c/
#include "add.h"
int add(int a, int b)
{
return a + b;
}
/sub.h/int sub(int a, int b);/sub.c/
#include "sub.h"
int sub(int a, int b)
{
return a - b;
}

静态库

  先将代码编译为目标文件:
在这里插入图片描述


生成静态库:ar(archive)是gnu归档工具,rc表示(replace and create)

  在Unix/Linux系统中,ar命令用于创建、修改和提取静态库(archive)。ar命令的常用选项包括:

  • r: 将一个或多个目标文件添加到归档文件中,如果已经存在则替换。
  • c: 创建一个新的归档文件,如果文件已经存在,则覆盖它。
  • s: 在归档文件中添加一个符号表,用于加快链接器的符号解析速度。
  • t:显示归档文件中的成员列表。可以使用ar t libexample.a命令列出libexample.a静态库中的所有目标文件。
  • x:从归档文件中提取一个或多个成员。例如,ar x libexample.a file1.o将从libexample.a静态库中提取file1.o目标文件。
  • d:从归档文件中删除一个或多个成员。可以使用ar d libexample.a file1.o命令从libexample.a静态库中删除file1.o目标文件。
  • p:打印归档文件中的成员内容。可以使用ar p libexample.a file1.o命令将file1.o目标文件的内容打印到标准输出。
  • v: 用于在执行操作时显示详细信息。它会将操作的进度和结果打印到标准输出,以便用户可以查看每个成员的处理情况
    在这里插入图片描述
      查看静态库中的目录列表:

在这里插入图片描述
  使用静态库:

  • -L 指定库路径
  • -l 指定库名
    在这里插入图片描述
    测试目标文件生成后,静态库删掉,程序照样可以运行:

  为了实现让程序自动找到静态库:
库搜索路径

  • 从左到右搜索-L指定的目录。
  • 由环境变量指定的目录 (LIBRARY_PATH)
  • 由系统指定的目录
      /usr/lib
      /usr/local/lib
    头文件也是很重要的,所以需要将其打包成静态库和头文件组织起来。
    静态库放入lib目录下,头文件放入include下
mylib
include
lib
add.h
sub.h
libMyMath.a

头文件放入/usr/include
库文件放入/usr/lib/usr/local/lib中的任意一个
在这里插入图片描述
  使用时还需用-l指明要链接的库在哪一个路径下,因为gcc在默认路径下链接的是C/C++库,只知道内置的库,不知道第三方库,所以需要显式的说明。

动态库

生成动态库

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 库名规则:libxxx.so

将相关文件打包为目标文件,这里和静态库略有不同:
在这里插入图片描述
链接目标文件,将其链接成共享库文件:
在这里插入图片描述
  将生成的共享库文件安装到适当的位置,以供其他程序使用
  如果您只想让某个程序使用该共享库,而不是所有程序,可以将共享库文件放在该程序的工作目录中,或将其路径添加到LD_LIBRARY_PATH环境变量中。
在这里插入图片描述
  上面的指令可能会让大家误会,实际上将共享库文件拷贝到系统共享库路径下和更改LD_LIBRARY_PATH选择其中一种就可以了。
  如果你将共享库文件放在了系统共享库路径下,那么搜索库时会去系统共享库路径下寻找,
  如果更改LD_LIBRARY_PATH,搜索库时会去LD_LIBRARY_PATH指定的路径下去寻找,这里的是LD_LIBRARY_PATH=.这个.代表当前目录,然而上图中我们将共享库文件拷贝到系统共享库路径下了,这个更改LD_LIBRARY_PATH相当于是无意义的。

库文件名称和引入库的名称

  如:libc.so -> c库,去掉前缀lib,去掉后缀.so,.a


    😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄

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

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

相关文章

Spring Boot 基础知识点1 (含面试题1)

Spring Boot 是一款基于 Spring 框架的开源应用程序开发工具,它旨在简化 Spring 应用程序的配置和开发过程。Spring Boot 提供了一种简单的方式来创建可独立运行的、生产级别的应用程序,并在需要时进行部署。Spring Boot 在微服务架构和云计算环境下得到…

报错curl: (6) Could not resolve host: raw.githubusercontent...的解决办法

我起初想要在macOS系统安装pip包,首先在终端安装homebrew,敲了命令:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent...)" 之后触发的报错,报错内容:curl: (6) Could not resolve host: raw.…

2024.1.7每日一题

LeetCode 383.赎金信 383. 赎金信 - 力扣(LeetCode) 题目描述 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。…

Python count()方法:统计字符串出现的次数与字符串拼接(包含字符串拼接数字)

Python count()方法:统计字符串出现的次数 count 方法用于检索指定字符串在另一字符串中出现的次数,如果检索的字符串不存在,则返回 0,否则返回出现的次数。 count 方法的语法格式如下: str.count(sub[,start[,end]]…

Ranger UserSync

作用 同步User到RangerDb 架构 解析 启动一个while(True) 进程定时同步,程序入口 source sink 掉接口获取Ranger User 并且Cache 计算delta 同步

如何编写高效的正则表达式?

正则表达式(Regular Expression,简称regex)是一种强大的文本处理技术,广泛应用于各种编程语言和工具中。本文将从多个方面介绍正则表达式的原理、应用和实践,帮助你掌握这一关键技术。 正则可视化 | 一个覆盖广泛主题…

元数据管理平台对比预研 Atlas VS Datahub VS Openmetadata

大家好,我是独孤风。元数据管理平台层出不穷,但目前主流的还是Atlas、Datahub、Openmetadata三家,那么我们该如何选择呢? 本文就带大家对比一下,这三个平台优势劣势。要了解元数据管理平台,先要从架构说起。 正文共&am…

如何把电脑中的项目快速传进Github中?

一、打开GitHub网站:https:github.com 登录自己的个人账号 1.新建一个项目 2.用鼠标直接拖拽电脑中的项目文件夹与文件到新创建的项目中点击保存即可。

Snipaste下载和使用

文章目录 前言一、Snipaste功能1.屏幕截图2.贴图功能3.图片编辑4.标注功能5.快捷键6.支持多屏7.安全可靠 二、使用步骤三、下载地址 总结 前言 Snipaste是一款简单但功能强大的截图工具,也可以将截图贴回到屏幕上。 一、Snipaste功能 1.屏幕截图 支持捕捉全屏、窗…

【好书推荐】我的第一本科技漫画书:漫画区块链

王杰,南京理工大学物理电子学硕士,曾担任乐视VR技术总监,现为北京米唐科技有限公司CEO,知乎“区块链”领域知名作者,北京信息科技大学、北京建筑大学、北京信息职业技术学院客座教授。 郑巍,擅长绘制钢笔淡…

用队列实现栈oj题——225

. 个人主页:晓风飞 专栏:LeetCode刷题|数据结构|Linux 路漫漫其修远兮,吾将上下而求索 文章目录 题目要求:实现 MyStack 类:注意:示例:解释:提示: 解题核心数据结构的定义…

进阶学习——Linux系统安全及应用

目录 一、系统安全加固 1.账号安全基本措施 1.1系统账号清理 1.1.1延伸 1.2密码安全控制 1.3命令历史限制 1.4终端自动注销 二、使用su命令切换用户 1.用途及用法 2.密码验证 3.限制使用su命令的用户 4.查看su操作记录 5.sudo(superuse do)…