当前位置: 首页 > news >正文

【Linux】软硬链接和动静态库

🔥 个人主页:大耳朵土土垚
🔥 所属专栏:Linux系统编程

这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉

文章目录

  • 1. 软硬链接
    • 💥硬链接(Hard Link)
    • 💥软链接(Symbolic Link)
  • 2. 动静态库
    • 💥静态库(Static Libraries)
    • 💥动态库(Dynamic Libraries)

1. 软硬链接

  在Linux系统中,文件链接分为两种类型:硬链接(Hard Link)和软链接(也称为符号链接或Symbolic Link)。它们都是用于创建文件的额外入口点,但是工作原理和使用场景有所不同。

💥硬链接(Hard Link)

  • 定义:硬链接是一个指向原始文件的直接链接。硬链接是一个与原始文件共享inode的文件,它们在文件系统中实际上是同一个文件

每个文件在Linux系统中都有一个inode,它包含了文件的所有元数据信息,如权限、所有者等,但不包含文件名。当创建一个硬链接时,实际上是为同一个inode创建了一个新的文件名,这意味着两个或多个硬链接实际上指向的是同一个文件数据

  • 特性
    • 硬链接不能跨文件系统。
    • 不能对目录创建硬链接(除了ln命令的特殊选项外,这通常是为了安全考虑)。
    • 对一个文件的修改会反映在所有的硬链接上
    • 如果原始文件被删除,只要还有一个硬链接存在,文件的数据就不会被删除。

删除原始文件后,硬链接仍然可以访问原始文件的内容,这是因为Linux系统在创建硬链接时,会使用引用计数的方式,记录一个文件共有多少个硬链接,当删除一个文件时,只有将其所有的硬链接都删除,这个文件才算真正的删除,否则都可以通过任意一个硬链接访问文件内容。

  • 创建方法:使用ln命令。例如,要为文件file.txt创建一个名为file-hard.link的硬链接,可以执行命令 ln file.txt file-hard.link。(注意文件的后缀可以随意选择)
    在这里插入图片描述

最开始创建file.txt文件,只有它自己,所以引用计数为1,后来为它新建了一个硬链接file-hard.link,引用计数就变为2,因为它们两个本质上是同一个文件,所以file-hard.link的引用计数也为2,与file.txt保持一致。

关于引用计数:
  新建一个目录文件,它一开始的硬链接引用计数就是2,除了它自己以外,它里面还包含一个隐藏文件.,这个其实也是该目录的硬链接,如下图所示:
在这里插入图片描述

而上图中的..文件则是指向上一级目录的硬链接,每个目录在创建的时候都会自动创建这两个文件。


💥软链接(Symbolic Link)

  • 定义:软链接是一个指向原始文件或目录的特殊文件,它包含了另一个文件或目录的路径名。通过访问软链接,可以间接访问源文件。

这意味着软链接形成的文件是不同于原始文件的,它们有着不同的inode编号,与硬链接不同

  • 特性

    • 软链接可以跨文件系统。
    • 可以对文件或目录创建软链接。
    • 如果原始文件或目录被移动或删除,软链接将失效(变为“断开”状态)。
    • 原始文件的权限信息、时间戳等软链接都是不保留的,它仅仅保存了原始文件的路径名。
  • 创建方法:使用ln -s命令。例如,要为文件sfile.txt创建一个名为sfile-soft.link的软链接,可以执行命令 ln -s sfile.txt sfile-soft.link

在这里插入图片描述

使用场景:

  • 硬链接适合于需要确保文件不会因为原文件的删除而丢失的情况,尤其是在同一文件系统内。减少磁盘空间占用以及创建备份文件等场景。
  • 软链接则更灵活,适用于需要跨文件系统链接或者链接到可能经常变动的位置的情况。此外,软链接可以更容易地识别和管理,因为它们本质上是文本形式的路径。

总结起来,软连接有独立的inode,软连接内容上保存的是目标文件的路径,当原始文件删除后,软链接将会失效;例如windows的快捷方式。而硬链接不是独立的文件,没有独立的inode,本质是一组文件名与目标文件的映射关系(别名),删除原始文件后,因为引用计数的存在,本质目标文件并没被删除,硬链接仍然可以访问原始文件的内容。


2. 动静态库

  在Linux系统中,库文件分为静态库(Static Libraries)和动态库(Dynamic Libraries)。这两种类型的库各有优缺点,适用于不同的场景。

💥静态库(Static Libraries)


定义

  • 静态库是在编译阶段就被链接到目标代码中的库。这意味着当一个程序被编译时,它会包含它所依赖的静态库的副本。

优点

  • 程序运行时不需要外部库文件,因为所有需要的代码都已经被整合进可执行文件中。
  • 可以确保程序总是使用特定版本的库,避免了所谓的“DLL地狱”问题(在Windows环境中常见,指的是由于不同应用程序可能依赖于不同版本的同一个库而导致的问题)。

缺点

  • 每个使用该库的程序都会有一个库的副本,这会导致磁盘空间的浪费。
  • 如果静态库需要更新,那么所有使用这个库的应用程序都需要重新编译和链接。

创建静态库

  1. 编写源代码并将其编译为目标文件(.o):gcc -c mystdio.c -o mystdio.o
  2. 创建静态库文件可以使用 ar 命令:ar rc libmystdio.a mystdio.o
  • libmystdio.a 是静态库文件的名称
  • mystdio.o 是要打包进库文件的目标文件
  • rc表示replace create

静态库通常具有 .a 扩展名。

使用静态库

方法一:使用带路径的库进行链接
gcc myprogram.c -I/path/to/include -L/path/to/library -lmylib -o myprogram

  • -I/path/to/include指定头文件所在的路径

  • -L/path/to/library 指定库文件所在的路径

  • -lmylib 指定要链接的库文件的名称(省略了前缀 lib 和文件扩展名 .a

  • 使用静态库进行链接时,可以使用 -l-L 选项指定库文件的位置和名称,-l指定库的名字

gcc在查动静态库时不会在当前目录下查,所以我们需要指定路径

方法二:将库安装到系统中直接使用

  1. 首先,编译源代码生成静态库文件(通常以.a为文件扩展名)。可以使用gccg++命令进行编译。例如,编译一个名为libexample.a的静态库文件可以使用以下命令:
gcc -c example.c                      # 编译源代码生成目标文件
ar rc libexample.a example.o         # 使用ar工具将目标文件打包成静态库
  1. 将生成的静态库文件复制到系统目录中,例如/lib64/。可以使用cp命令进行复制,例如:
sudo cp libexample.a /lib64/  # 将静态库文件复制到系统目录
sudo cp  libexample.h /usr/include/ #将静态库头文件复制到系统目录
  1. 更新库缓存。在某些Linux发行版中,需要手动更新库缓存以使系统可以找到新安装的库。可以使用以下命令更新库缓存:
sudo ldconfig                        # 更新库缓存
  1. 确认安装成功。可以使用ls命令检查静态库文件是否已经复制到系统目录中,例如:
ls /lib64/libexample.a        # 检查静态库文件
  1. 在编译和链接其他程序时,可以使用-l选项指定使用安装的静态库。例如,使用gcc命令编译一个名为example_program.c的程序,并链接使用静态库libexample.a可以使用以下命令:
gcc example_program.c -o example_program -lexample

链接库时需要省去前缀lib和后缀.a,动态库也是一样,直接 -lexample即可

这样,就可以将静态库安装到系统中,并且可以直接在其他程序中使用该库。

💥动态库(Dynamic Libraries)


定义

  • 动态库(也称为共享库)是在程序运行时被加载的。这意味着多个程序可以共享同一份库文件,从而节省内存和磁盘空间。

优点

  • 节省磁盘空间和内存,因为多个程序可以共享同一个库文件。
  • 库更新时不需要重新编译或重新链接应用程序,只需替换库文件即可(前提是API没有改变)。

缺点

  • 程序运行时需要有相应的动态库存在,否则可能会导致程序无法启动。

创建动态库

  • 动态库通常具有 .so (shared object) 扩展名。
  • 创建动态库可以使用 gcc 编译器的 -fPIC-shared 选项。

例如,编译一个名为libexample.so的动态库文件可以使用以下命令:

gcc -fPIC -c example.c   #编译.o文件
gcc -shared -o libexample.so example.o    # 编译源代码生成动态库

-fPIC:形成与位置无关码

使用动态库

方法一:使用带路径的库进行链接

这里与静态库一致

gcc myprogram.c -I/path/to/include -L/path/to/library -lmylib -o myprogram

  • -I/path/to/include指定头文件所在的路径

  • -L/path/to/library 指定库文件所在的路径

  • -lmylib 指定要链接的库文件的名称(省略了前缀 lib 和文件扩展名 .a

  • 使用动态库进行链接时,可以使用 -l-L 选项指定库文件的位置和名称,-l指定库的名字

  • 可以使用 ldd 命令查看一个程序所依赖的动态库列表,例如:ldd myprogram

gcc在查动静态库时不会在当前目录下查,所以我们需要指定路径

注意链接动态库形成可执行程序后,运行可执行文件时,系统是需要找到动态库的位置,也就是运行可执行程序时,动态库是需要加载的,所以如何让系统找到动态库?

  1. 将动态库文件复制到系统目录中,系统会默认在该目录下寻找
  2. 在系统路径建立动态库文件的软链接
  3. Linux系统中除了会在系统路径下寻找动态库,还会在环境变量中寻找,该环境变量为LD_LIBRARY_PATH
  4. ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新

方法二:将库安装到系统中直接使用

  1. 将生成的动态库文件复制到系统目录中,例如/lib64。可以使用cp命令进行复制,例如:
sudo cp libexample.so /lib64/    # 将动态库文件复制到系统目录
sudo cp  libexample.h /usr/include/ #将静态库头文件复制到系统目录
  1. 更新库缓存。在某些Linux发行版中,需要手动更新库缓存以使系统可以找到新安装的库。可以使用以下命令更新库缓存:
sudo ldconfig                        # 更新库缓存
  1. 确认安装成功。可以使用ls命令检查动态库文件是否已经复制到系统目录中,例如:
ls /lib64/libexample.so      # 检查动态库文件
  1. 在编译和运行其他程序时,可以使用-l选项指定使用安装的动态库。例如,使用gcc命令编译一个名为example_program.c的程序,并链接使用动态库libexample.so可以使用以下命令:
gcc example_program.c -o example_program -lexample

这样,就可以将动态库安装到系统中,并且可以直接在其他程序中使用该库。此外,编译形成可执行程序后,如果删除了需要的动态库,程序也是不可以运行的。

原理上理解动态库:

在这里插入图片描述

进程在链接动态库时,操作系统会先将动态库加载到内存中,然后将动态库在内存中的地址通过页表映射到进程地址空间的共享区,这样进程在执行库方法的时候就是在自己的地址空间中跳转运行的。当另一个程序也要使用同一个动态库时就不需要再重复加载该动态库到内存里了,只需要通过进程的页表进行映射之前加载到内存的动态库即可,多个程序也是这样。

总结
  如果同时提供动态库与静态库,gcc/g++默认使用动态库;如果要使用静态库必须使用静态链接-static来指明;如果使用动态链接但是只有静态库,那么gcc/g++只能选择静态库进行链接。
  选择使用静态库还是动态库取决于具体的需求。如果关注程序的独立性和稳定性,且不介意较大的程序大小,可以选择静态库;如果更关心资源的有效利用,并且可以保证目标系统上有适当的动态库版本,那么使用动态库是更好的选择。

相关文章:

【Linux】软硬链接和动静态库

🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…...

HarmonyOS入门 : 获取网络数据,并渲染到界面上

1. 环境搭建 开发HarmonyOS需要安装DevEco Studio,下载地址 : https://developer.huawei.com/consumer/cn/deveco-studio/ 2. 如何入门 入门HarmonyOS我们可以从一个实际的小例子入手,比如获取网络数据,并将其渲染到界面上。 本文就是基于…...

【贪心】【哈希】个人练习-Leetcode-1296. Divide Array in Sets of K Consecutive Numbers

题目链接:https://leetcode.cn/problems/divide-array-in-sets-of-k-consecutive-numbers/description/ 题目大意:给出一个数组nums[]和一个数k,求nums[]能否被分成若干个k个元素的连续的子列。 思路:比较简单,贪心就…...

【数据库实验一】数据库及数据库中表的建立实验

目录 实验1 学习RDBMS的使用和创建数据库 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六、实验结果 七、评价分析及心得体会 实验2 定义表和数据库完整性 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六…...

Web服务nginx基本实验

安装软件: 启动服务: 查看Nginx服务器的网络连接信息,监听的端口: 查看默认目录: 用Windows访问服务端192.168.234.111的nginx服务:(防火墙没有放行nginx服务,访问不了) …...

Ubuntu实现双击图标运行自己的应用软件

我们知道在Ubuntu上编写程序,最后编译得到的是一个可执行文件,大致如下 然后要运行的时候在终端里输入./hello即可 但是这样的话感觉很丑很不方便,下边描述一种可以类似Windows上那种双击运行的实现方式。 我们知道Ubuntu是有一些自带的程序…...

js id字符串转数组

将一个逗号分隔的字符串(例如 "12,123,213,")转换为一个 JavaScript 数组,并去除多余的逗号,可以使用以下几种方法。这里我将展示几种常见的方式: 方法 1: 使用 split 和 filter 你可以使用 split 方法将字…...

《手写Spring渐进式源码实践》实践笔记(第十八章 JDBC功能整合)

文章目录 第十八章 JDBC功能整合背景技术背景JDBC JdbcTemplate关键特性 用法示例业务背景 目标设计实现代码结构类图实现步骤 测试事先准备属性配置文件测试用例测试结果: 总结 第十八章 JDBC功能整合 背景 技术背景 JDBC JDBC(Java Database Conne…...

边缘计算在智能交通系统中的应用

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 边缘计算在智能交通系统中的应用 边缘计算在智能交通系统中的应用 边缘计算在智能交通系统中的应用 引言 边缘计算概述 定义与原…...

HTML5+css3(浮动,浮动的相关属性,float,解决浮动的塌陷问题,clear,overflow,给父亲盒子加高度,伪元素)

浮动的相关属性 以下使浮动的常用属性值: float: 设置浮动 以下属性: left : 设置左浮动 right : 设置右浮动 none :不浮动,默认值clear 清除浮动 清除前面兄弟元素浮动元素的响应 以下属性: left &…...

【C++ 滑动窗口】2134. 最少交换次数来组合所有的 1 II

本文涉及的基础知识点 C算法:滑动窗口及双指针总结 LeetCode2134. 最少交换次数来组合所有的 1 II 交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。 环形 数组是一个数组,可以认为 第一个 元素和 最后一个 元素 相邻 。 给你一个 二…...

使用 PyTorch 实现并测试 AlexNet 模型,并使用 TensorRT 进行推理加速

本篇文章详细介绍了如何使用 PyTorch 实现经典卷积神经网络 AlexNet,并利用 Fashion-MNIST 数据集进行训练与测试。在训练完成后,通过 TensorRT 进行推理加速,以提升模型的推理效率。 本文全部代码链接:全部代码下载 环境配置 为了保证代码在 GPU 环境下顺利运行,我们将…...

Python 数据可视化详解教程

Python 数据可视化详解教程 数据可视化是数据分析中不可或缺的一部分,它通过图形化的方式展示数据,帮助我们更直观地理解和分析数据。Python 作为一种强大的编程语言,拥有丰富的数据可视化库,如 Matplotlib、Seaborn、Plotly 和 …...

springboot集成opencv开源计算机视觉库

最近项目需要用到opencv,网上看到很多资料都是下载安装并且引入jar包与dll文件,感觉很麻烦,不是我想要的,于是花时间折腾了下,不需要任何安装与引入jar包与dll文件,简单方便,快速上手。 先说说…...

CCF ChinaOSC |「开源科学计算与系统建模openSCS专题分论坛」11月9日与您相约深圳

2024年11月9日至10日,以“湾区聚力 开源启智”为主题的2024年中国计算机学会中国开源大会(CCF ChinaOSC)将在深圳召开。大会将汇聚国内外学术界、顶尖科技企业、科研机构及开源社区的精英力量,共同探索人工智能技术和人类智慧的无…...

2024年11月8日上海帆软用户大会

2024年11月8日上海帆软用户大会 2024年11月8日,上海成功举办了帆软用户大会,主题为“数字聚力,绽放新机”。大会汇聚了众多行业专家和企业代表,共同探讨数字化转型和商业智能领域的最新趋势和实践。 大会亮点: 专家…...

信息泄露漏洞一文速通

文章目录 信息泄露漏洞一文速通敏感信息の概念敏感信息の分类企业敏感信息用户敏感信息站点敏感信息 如何挖掘信息泄露漏洞?信息泄露风险清单(checklist)未授权访问类文件与数据泄露开发与调试信息泄露公共配置文件泄露其他敏感信息泄露点 威…...

Android 启动时应用的安装解析过程《二》

上一篇内容说到InitAppsHelper这个类的initSystemApps函数,只说了一下几个重要参数的来源还没展开,这里继续,有兴趣的可以看链接: Android 启动时应用的安装解析过程《一》 一、系统应用的扫描安装 /*** Install apps from system dirs.*/Gu…...

智谱AI:ChatGLM强大的生成式语言模型

目录 智谱AI:ChatGLM强大的生成式语言模型 一、ChatGLM的定义与特点 二、ChatGLM的应用场景 三、举例说明 四、注意事项 智谱AI:ChatGLM强大的生成式语言模型 它通过对话的方式能够生成自然流畅的文本,这一特性使其在多个领域都有广泛的应用潜力,特别是在智能对话和智能…...

git tag

已经发布了 v1.0 v2.0 v3.0 三个版本,这个时候,我突然想不改现有代码的前提下,在 v2.0 的基础上加个新功能,作为 v4.0 发布。就可以检出 v2.0 的代码作为一个 branch ,然后作为开发分支。 要查看仓库中的所有标签 gi…...

python打卡day49

知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...

第八部分:阶段项目 6:构建 React 前端应用

现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...