【Linux-基础IO】软硬链接+动静态库

一、软硬链接

见一见

  • 软连接

  • 硬连接 

通过观察我们发现以下几点:

1.ll - i后,软连接形成的文件有指向,并且软连接的Inode编号与对应文件的Inode编号不一样

2.ll - i后,硬连接形成的文件与对应的文件Inode编号一样

3.软连接的硬连接数为1,硬连接的硬连接数为2

特征+作用

  1. 软连接是一个独立的文件,因为有独立的inode number

软连接的内容:目标文件所对应的路径字符串;也就是我们可以通过cat软连接,就能够打印文件的内容,软连接也就类似于windows中的快捷键,比如桌面看到的软件保存的是其它的路径,在系统中可能你要运行的可执行程序在一个很深的目录下,就可以在较上层的目录中建立软链接。

 

【问题】我们把软连接删除了会影响目标文件吗?

并不会,因为它们两个是独立的文件;就像小白刚接触电脑一样,卸载软件只是把快捷方式拖到回收站,其实并没有删除软件;但是目标文件删除了,软连接绝对跑不出来的

【软连接的作用】--快速使用文件

我们现在要在外层建立软连接,目标文件在lesson21内部,测试发现通过cat外层的软连接,也可以打印文件里的内容

在系统中 ll /usr/lib64有很多库,包括动态库静态库等,我们就可以发现这里有很多软连接 

  1. 硬连接不是一个独立的文件,因为它没有独立的inode number,它用的是目标文件的inode

硬连接(Hard Link)是一种特殊的文件系统特性,它允许用户创建多个指向同一inode(索引节点)的文件名。硬连接使得一个文件可以有多个名称,每个名称都指向文件系统的同一数据块集合

硬连接的创建和删除:

  • 创建硬连接:使用ln命令可以创建硬连接,例如ln -s 原始文件 硬连接文件

  • 删除硬连接:要删除硬连接,需要删除原始文件或所有指向同一inode的硬连接。例如,使用rm 硬连接文件可以删除硬连接,但如果原始文件仍然存在,硬连接文件会重新创建。

硬连接的特点:

  1. inode共享:硬连接允许多个文件名指向同一inode。这意味着,对于硬连接文件,只有原始文件(即创建硬连接的文件)的inode会被删除或重命名,其他硬连接文件仍然有效。

  2. 文件内容共享:由于硬连接共享相同的inode,它们共享文件的所有数据块。这意味着,对其中一个硬连接文件进行的修改会立即反映在所有硬连接文件上。

  3. 不可跨文件系统:硬连接必须在同一文件系统中创建,因为inode是文件系统内部的唯一标识。

  4. 不可跨目录:硬连接不能跨目录创建,每个硬连接必须位于原始文件的目录内。

  5. 无法创建到目录:硬连接不能创建到目录,因为目录的inode包含了指向子目录和文件的指针,而不是文件的数据。

  6. 文件删除限制:删除原始文件不会删除其他硬连接文件,因为它们共享同一个inode。要删除所有硬连接文件,必须先删除所有硬连接。

硬连接的用途:

  1. 文件备份:通过创建硬连接,可以创建文件的备份,而不需要复制文件的内容。

  2. 链接文件:在某些情况下,硬连接可以用来创建多个文件名指向同一数据,例如,在文件名发生冲突时,可以创建一个硬连接来指向正确的文件。

  3. 目录管理:硬连接可以用来简化目录结构,例如,在目录中创建一个指向主目录的硬连接,以方便访问。

【知识点】关于文件属性硬连接数

硬连接数(Hard Link Count)是指一个文件系统中某个inode(索引节点)所拥有的硬连接数量。每个inode在文件系统中都是唯一的,它用于存储文件或目录的元数据和指向数据块的指针。硬连接数是指有多少个文件名指向这个inode

硬连接数与文件删除行为有关:

  1. 硬连接数减少:当一个硬连接被删除时,指向该inode的硬连接数会减少。如果原始文件(即创建硬连接的文件)的硬连接数降至零,那么该文件及其数据块将被删除。

  2. 文件删除限制:即使原始文件被删除,只要还有其他硬连接指向该inode,文件的数据块就不会被删除。这是因为文件系统认为文件仍然在使用中,因此不能释放其数据块。

  3. 硬连接数限制:不同的文件系统可能有不同的硬连接数限制。例如,某些文件系统可能不允许创建超过一定数量的硬连接。

 我们先看hard_link中file_hard.link 与 file.txt的硬连接数为2,这就说明这两个文件指向的是同一块空间,通过两个任意一个文件都可以访问这块空间。

我们此时再创建一个目录,发现目录的硬连接数为2这是为什么呢?

因为一个目录中有隐藏文件,隐藏文件分别是 .当前路径 ..上级目录,正是因为有这两个隐藏文件,我们才可以使用cd..,也就是说任何一个目录,刚开始新建的时候,引用计数一定是2

当前目录下新建一个目录,上级目录的硬连接数会增加,因为新目录的名称指向了上级目录的inode。

目录A内部,新建一个目录,会让A目录的引用计数自动+1,一个目录内部有几个目录:A引用计数-2

注意:在Linux系统中,不允许给目录建立硬连接,目的是为了避免形成路径环绕

 

二、动静态库

在Linux操作系统中,库文件(Library)分为动态库(Dynamic Libraries)和静态库(Static Libraries)。它们是共享代码和资源的方式,用于在编译和运行时提供给应用程序使用。

  • 动态库(Dynamic Libraries)

动态库在运行时加载,它们通常以.so(在Linux上)或.dll(在Windows上)为扩展名。动态库的好处是它们可以在程序运行时被动态加载,这意味着应用程序不需要将库代码包含在可执行文件中,从而减小了可执行文件的大小。

动态库的使用步骤如下:

  1. 编译时链接:在编译应用程序时,链接器(Linker)会查找动态库的路径,并链接到相应的库文件。

  2. 运行时加载:当应用程序运行时,操作系统会动态加载指定的动态库,并将其内容加载到内存中。

  3. 链接器处理:链接器会处理动态库的链接信息,并将相应的函数和数据映射到应用程序的内存空间。

  4. 内存管理:动态库的内容被加载到内存中,应用程序可以直接调用库中的函数。当应用程序结束时,操作系统会负责释放动态库占用的内存。

  • 静态库(Static Libraries)

静态库在编译时链接,它们通常以.a为扩展名。静态库将库代码直接包含在可执行文件中,这使得可执行文件的大小变大,但好处是应用程序不需要在运行时动态加载库,从而提高了运行效率。

静态库的使用步骤如下:

  1. 编译时链接:在编译应用程序时,链接器会将静态库的内容直接包含到可执行文件中。

  2. 运行时加载:由于静态库已经被包含在可执行文件中,因此应用程序不需要在运行时动态加载库。

  3. 内存管理:静态库的内容被包含在可执行文件中,应用程序可以直接调用库中的函数。当应用程序结束时,静态库占用的内存与可执行文件一起被释放。

静态库的制作打包与使用

【故事引入】

张三是一名学霸,李四是位学渣;现在老师要求自己写一个math库和print库并且能够实现;李四什么也不会,于是就找张三说:“张三,这份作业你帮我做呗,你把代码给我,我请你吃顿饭”;张三一想:这个可以唉,但是如果我把我的源代码给了李四,老师一看就知道我们两个作业是一样的,于是张三将几个.c代码实现的文件,打包成库,复制给李四,然后教李四怎么调用这个库文件,于是这个作业就这样过去了

下面是张三的文件和代码

 

生成静态库

  • gcc -c mymath.c -o mymath.o / gcc -c myprint.c -o myprint.o

先讲源文件汇编后盛出.o文件,但是它还不能运行,因为还差最后一步链接;

  • ar -rc libwork.a mymath.o myprint.o

 

ar(Archiver)是一个用于创建和维护静态库的工具,它通常与GNU Binutils工具集一起提供。ar命令允许您创建新的静态库、修改现有库、提取库中的文件、列出库中的内容等。

指令ar -rc libwork.a mymath.o myprint.o的解释如下:

  1. ar:这是Archiver命令的名称。

  2. -r:这个选项用于增加(add)文件到库文件中。当您使用-r选项时,ar会添加指定的对象文件(.o文件)到库文件中。

  3. -c:这个选项用于创建(create)一个新的库文件。如果您没有指定库文件,ar会创建一个新的库文件。如果您指定了库文件,ar会创建一个新版本的库文件。

  4. libwork.a:这是库文件的名称,.a是静态库文件的扩展名。

  5. mymath.o:这是您想要添加到库文件中的第一个对象文件。

  6. myprint.o:这是您想要添加到库文件中的第二个对象文件。

当您运行这个指令时,ar会创建一个新的库文件(如果它还不存在)或更新现有的库文件。它会将mymath.omyprint.o这两个.o文件添加到库文件libwork.a中。这些.o文件包含了编译后的C语言代码,当它们被添加到库文件中时,它们会与库文件中的其他.o文件链接,以便在程序中使用。

★ps:库文件开头必须以lib开头

  • 查看静态库中的目录列表

 

main.c内容

#include "mymath.h"
#include "myprint.h"
int main(){
  Print("hello I am Print\n");
  return 0;
}

我们编译发现没有这样的文件或目录,原因就是 mymath.h 既不在当前路径下,也不在默认路径下。所以我们要告诉编译器,你要往哪个地方去找头文件,于是需要加一个选项-I + 指定路径

 

此时还有报错,但是与上一次相比,这次我们找到了头文件,但是链接器在尝试链接可执行文件时找不到名为Print的函数,所以还需要在gcc上加入-L + 路径选项,告诉编译器从哪里链接

 

此时又报错了,这是因为我们指明了库的路径,但是没有指明是哪一个库,万一这里面有几百上千的库总不能让编译器一个一个去找吧,于是后面还需要加上是哪个库,加上--l + 库名称

★ 真正库的名称需要去掉前缀lib和后缀.a

库搜索路径

1.从左到右搜索 -L 指定的目录

2.由环境变量指定的目录(LIBRARY_PATH)

3.由系统指定的目录/usr/lib /usr/local/lib

动态库的打包与使用

依旧是之前的代码和文件

生成动态库

首先,需要分别编译mymath.cmyprint.c文件,生成.o文件

gcc -fPIC -c myprint.c -o myprint.o
gcc -fPIC -c mymath.c -o mymath.o

 

这里使用到的-PIC是位置无关代码(PIC,Position Independent Code)是一种特殊的编译代码格式,它允许编译器生成的代码在内存中的任何位置执行,而不会产生错误或性能问题。PIC代码的一个关键特性是它不依赖于程序在内存中的加载地址。后续我们介绍原理,这里我们先使用

  • gcc -shared -o libwork.so myprint.o mymath.o

-shared:这是一个选项,告诉编译器创建一个共享库(Shared Object)而不是一个可执行文件。共享库可以在多个程序之间共享,并且可以被动态加载和链接到程序中。

然后打包发给李四

使用动态库

main.c内容

#include "mymath.h"
#include "myprint.h"

int main(){
  Print("I am Print()\n");;
  printf("%d + %d = %d\n",5,15,add(5,15));

  return 0;
}

此时我们执行代码

 

什么情况?怎么还报错,怎么就找不到

我们用ldd查看一下链接情况

 

这是因为LD_LIBRARY_PATH环境变量的问题:运行可执行文件时,它可能会使用LD_LIBRARY_PATH环境变量来查找库文件。如果这个环境变量没有正确设置,或者它不包含./lib目录,那么可执行文件就无法找到库文件。可以设置LD_LIBRARY_PATH环境变量,或者将其包含在~/.bashrc~/.bash_profile文件中。

这个是动态库,因为动态库要在程序运行的时候,要找到动态库加载并运行!

这样我们就连到了

 

静态库为什么没有这个问题??

因为编译期间,已经将库中的代码拷贝到我们的可执行程序内部了!加载和库就没有关系了!

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从零开始在Windows系统上搭建一个node.js后端服务项目

目录 一、下载node.js及配置环境 二、搭建node.js项目及安装express框架 三、集成nodemon,实现代码热部署 四、Express 应用程序生成器 一、下载node.js及配置环境 网上很多安装教程,此处就不再赘述了 版本信息 C:\Users\XXX>node -v v20.15.0…

一个纹理分割的例子

纹理是图像分割常用的特征,即使不是纹理分割。Rafael Gonzalez和Richard Woods的《数字图像处理》中这部分内容片面了。 给一个利用简单的统计特征——熵进行纹理分割的例子。这个例子是说明阈值分割不是仅适用于灰度值的情况,也可以用于纹理&#xff…

【into outfile写文件】

简介 select * from user into outfile C:/Users/ichunqiu/Desktop/PhpStudy2018/PHPTutorial/WWW/1.txt;用法的意思就是把user表中查询到的所有字段都导出到1.txt文件中 我们之前还有学到dumpfile,单是它只能导出一条数据 写入shell 测试注入点 usernameadmin&…

SAP SD学习笔记09 - 受注传票中的不完全Log 和 Business Partner(取引先机能)

好久没写SD了,今天继续写。 上一章讲了SD的如下知识 - SD的售前的流程(引合和見積(询价和报价)) - 数据流的概念,主要就是后传票可以参照前传票,以实现数据的流动,减少输入 - Co…

C++之“构造函数”

文章目录 类的默认成员函数构造函数 类的默认成员函数 默认成员函数就是我们没有在main函数里调用,但是编译器会自动生成的成员函数称为默认成员函数。 C由8个默认成员函数,我们暂时了解6个。 默认成员函数:构造函数,析构函数&a…

面试应该问什么?

在求职者面试的过程中,向面试官提问是一个展现自己积极态度、对职位和公司兴趣以及进一步了解工作环境和职业发展机会的重要环节。以下是一些求职者可以在面试中向面试官提问的问题,这些问题旨在帮助你更全面地了解未来的工作环境、团队文化、以及个人职…

adb devices没找到安卓设备的解决办法

要想让设备让adb识别到,要开启设备的开发者模式,并且开启USB调试功能: 然后重新运行:就找到了

java 文件File类概述

前言 在Java中,File类是一个与文件和目录(文件夹)路径名相关的抽象表示形式。它是java.io包中的一个重要类,用于表示和操作文件系统中的文件和目录。 File类的基本概念 表示路径:File类既可以表示文件路径&#xff…

OpenCV高级图形用户界面(8)在指定的窗口中显示一幅图像函数imshow()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在指定的窗口中显示一幅图像。 函数 imshow 在指定的窗口中显示一幅图像。如果窗口是以 cv::WINDOW_AUTOSIZE 标志创建的,图像将以原…

操作系统 和 初识进程

目录 操作系统(OS) 进程 操作系统(OS) 概念 操作系统即os,是一款软件。 任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。 操作系统的本质是一种进行软硬件管理的软件 笼统的理解&#xf…

用Java做智能客服,基于私有知识库

构建Java智能客服系统的整体思路 使用Java构建智能客服系统的整体思路是: 首先将客服QA文档以Word形式导入到系统中,通过向量化处理存入知识库。 当用户提出问题时,系统会根据问题内容从知识库中检索相关的上下文信息,并结合大…

字节跳动实习生投毒自家大模型细节曝光 影响到底有多大?

10月19日,字节跳动大模型训练遭实习生攻击一事引发广泛关注。据多位知情人士透露,字节跳动某技术团队在今年6月遭遇了一起内部技术袭击事件,一名实习生因对团队资源分配不满,使用攻击代码破坏了团队的模型训练任务。 据悉&#xf…

【动态规划】【斐波那契数列模型】解码方法

解码方法 91. 解码方法 算法原理 确定状态表示 经验题目要求:以 i 位置为结尾dp[i] 表示以 i 位置为结尾时,解码方法的总数 状态转移方程 定义好状态表示,我们就可以分析 i 位置的 dp 值,如何由 [前面] 或者 [后面] 的信息推…

Leetcode 1137. 第 N 个泰波那契数

原题链接&#xff1a;Leetcode 1137. 第 N 个泰波那契数 代码1&#xff1a; class Solution { public:int a[40];int tribonacci(int n) {a[0]0;a[1]1;a[2]1;if(n<1) return n;if(a[n]) return a[n];a[n]tribonacci(n-1)tribonacci(n-2)tribonacci(n-3);return a[n];} };代…

【LeetCode】每日一题 2024_10_19 使二进制数组全部等于 1 的最少操作次数 II(贪心)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;使二进制数组全部等于 1 的最少操作次数 II 力扣每日一题刷新规律&#xff0c;昨天刷新了 I&#xff0c;那今天必定有 II。 代码与解题思路 今天的题目和昨天的非常像&#xff0c;只有一…

SVM支持向量机python实现

支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种强大的监督学习算法&#xff0c;主要用于分类和回归任务。SVM的核心思想是找到一个最优的超平面&#xff0c;使得不同类别的数据点能够被尽可能清晰地分开&#xff0c;并且这个超平面与最近的数据点之间有…

SpringCloud无介绍快使用,单机Eureka服务注册中心cloud-eureka-server7001搭建(十)

TOC 问题背景 从零开始学springcloud微服务项目 注意事项&#xff1a; 约定 > 配置 > 编码IDEA版本2021.1这个项目&#xff0c;我分了很多篇章&#xff0c;每篇文章一个操作步骤&#xff0c;目的是显得更简单明了controller调service&#xff0c;service调dao项目源码以及…

微软的 Drasi:一种轻量级的事件驱动编程方法

微软的开源数据变化处理平台有望提供一种全新的方式来构建和管理可产生持续事件流的云应用程序。 Microsoft Azure 孵化团队是微软超大规模云中比较有趣的组成部分之一。它介于传统软件开发团队和研究组织之间&#xff0c;致力于构建大规模分布式系统问题的解决方案。 这些解决…

Kettle9.4支持Clickhouse数据源插件开发以及性能测试

前言 最近业务这边有个指标需要用到大数据这边的列式数据库进行处理&#xff0c;由于kettle不支持clickhouse数据源驱动&#xff0c;这里查了一下网上的相关资料&#xff0c;发现了一些别人开发好的驱动包&#xff0c;下载下来后使用效果不尽人意。总结下来有以下几个问题&…

【C++】string类(接口使用详解 下)

我们接着【C】string类&#xff08;接口使用详解 上&#xff09;-CSDN博客 继续介绍string的使用。 1.string类对象的修改操作 我们就说一下用的比较多的接口。 1.1 operator 这个接口可以尾插一个字符&#xff0c;或者一个字符串&#xff0c;或者一个对象。 string s1(&qu…