【linux深入剖析】深入理解软硬链接 | 动静态库的制作以及使用


🍁你好,我是 RO-BERRY
📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油

在这里插入图片描述


目录

  • 1.理解软硬链接
    • 1.1 操作观察现象
      • 软链接
      • 硬链接
    • 1.2 软硬链接的原理
      • 测试硬链接
      • 测试软链接
    • 1.3 软硬链接的应用场景
      • 1.3.1软链接
      • 1.3.2 硬链接
  • 2.动静态库
    • 2.1 动静态库的制作和使用
      • 准备工作
      • 生成静态库
      • 生成动态库
    • 2.2 将自己的库打包给别人


1.理解软硬链接

软链接和硬链接是在Linux系统中常见的文件链接方式。

软链接(Symbolic Link): 软链接是一个指向目标文件或目录的特殊文件,类似于Windows系统中的快捷方式。软链接可以跨文件系统,可以链接到目录,也可以链接到文件。软链接的特点是:

  1. 软链接文件有自己的inode和文件名,但是数据块内容是指向目标文件的路径。
  2. 删除软链接不会影响目标文件。
  3. 软链接可以跨文件系统,即可以链接到不同的磁盘分区。

硬链接(Hard Link): 硬链接是指多个文件名指向同一个inode,它们共享同一份数据块内容。硬链接的特点是:

  1. 硬链接文件和目标文件具有相同的inode和数据块内容。
  2. 删除任意一个硬链接文件不会影响其他硬链接文件和目标文件。
  3. 硬链接只能链接到文件,不能链接到目录。
  4. 硬链接不能跨文件系统,即只能在同一个磁盘分区内创建。

1.1 操作观察现象


指令ln -s

ln -s是Linux系统中的一个命令,用于创建软链接(symbolic link)。软链接是一种特殊的文件,它指向另一个文件或目录。通过软链接,可以在不改变原始文件或目录位置的情况下,创建一个指向它的链接。

使用ln -s命令创建软链接的语法如下:

ln -s <原始文件或目录路径> <链接文件路径>

  • 其中,<原始文件或目录路径>是要创建链接的文件或目录的路径,<链接文件路径>是要创建的软链接的路径。
    例如,假设当前目录下有一个文件file.txt,我们可以使用以下命令创建一个指向它的软链接:
    ln -s file.txt link.txt
    这样就创建了一个名为link.txt的软链接,它指向file.txt文件。

需要注意的是,软链接是一个指向原始文件或目录的引用,而不是实际的文件或目录本身。删除软链接不会影响原始文件或目录,但删除原始文件或目录可能会导致软链接失效。


指令ll -li

ll -li是一个Linux命令,用于显示文件或目录的详细信息,并以inode号进行排序。下面是该命令的一些说明:

  • ll是 “ls -l” 的简写,用于显示文件和目录的详细信息。
  • -li是两个选项的组合,其中 -l表示以长格式显示文件信息,包括文件权限、所有者、大小、修改日期等;而 -i表示显示文件的inode号。

通过执行 ll -li 命令,您将看到当前目录下所有文件和目录的详细信息,并按照inode号进行排序。


软链接

在这里插入图片描述结论:软链接本质上就是一个文件,有独立的inode


指令ln

在Linux系统中创建文件硬链接,可以通过ln命令来创建硬链接。ln命令的语法如下:

ln [选项] <源文件或目录> <目标文件或目录>

其中,源文件或目录是要创建链接的文件或目录的路径,目标文件或目录是要创建的链接的路径。

创建硬链接的命令格式为:

ln <源文件> <目标文件>

例如,要在当前目录下创建一个名为linkfile的硬链接,指向源文件sourcefile,可以使用以下命令:
ln sourcefile linkfile

注意,硬链接只能链接到同一个文件系统中的文件,且不能链接到目录。


硬链接

在这里插入图片描述

我们创建了硬链接之后可以发现。前面的文件信息发生了一个微小的变化,也就是文件权限后面的数字由1变成了2,而硬链接新出现的文件其初始数字就是2,这个数字从来没有讲述过

在这里插入图片描述

我们查看一下inode也可以发现,新出现的文件与旧文件inode竟然是一样的!

在这里插入图片描述
结论:硬链接本质不是一个独立的文件,因为它的inode编号和目标文件相同


1.2 软硬链接的原理

测试硬链接

  • 我们将硬链接的目标文件写入点数据
    在这里插入图片描述

可以看到我们修改目标文件的同时,硬链接生成的文件也会发生变化,其大小与目标文件同样是12,且修改时间相同,inode也没有改变

  • 我们删除目标文件
    在这里插入图片描述

可以看到,我们的硬链接产生的文件并没有什么变化,我们查看其文件数据可以清楚的看到,这个数据就是我们当初输入到目标文件的数据,这是什么情况?

其实也可以理解,其inode和目标文件是一摸一样的,也就是说他们对应的都是同一个文件,我们硬链接的工作特别像给目标文件进行一个重命名,并且源文件不改变。

硬链接的本质:一定没有新建文件,因为没有新的inode,只是新建了一个文件名,与目标文件inode相同的映射关系。


这个时候我们再看当初的这个2
在这里插入图片描述

其实这就是一个硬链接数,表明有多少个硬链接,表明了有多少个文件名与这一块数据有相同的映射关系,同时也叫引用计数

同时可以看到,硬链接就是建立了一个映射关系同时对引用计数++即可。

我们删掉文件后可以看到,引用计数从2变成了1
在这里插入图片描述


测试软链接

在这里插入图片描述
软链接创建的文件有独立的inode,有独立的inode那么就有独立的属性以及独立的数据内容。

软链接本质就是一个独立文件,软链接内容里面放的目标文件的路径!

软链接就相当于我们Windows里面的快捷方式,其存储的就是其可执行程序的路径

1.3 软硬链接的应用场景

1.3.1软链接

  • 我们创建一系列文件并输入内容给test.c

在这里插入图片描述

#include<stdio.h>
int main()
{printf("hello world\n");return 0;
}
  • 将文件编译,并把可执行文件移动到bin目录下

在这里插入图片描述

  • 我们想访问这个可执行文件就只能访问绝对路径访问

在这里插入图片描述

  • 我们还可以采用软链接的方式访问到这个可执行文件

在这里插入图片描述
我们就可以使用软链接的方式,在当前目录创建一个软链接的文件,这样就可以直接访问到深路径的文件,我们使用起来就更加方便


我们也可以采用硬链接的方式来达到访问深路径的文件
在这里插入图片描述

软链接使用起来还是更加方便一些,一般推荐软链接


系统有很多的软链接

ls -l /lib64/

在这里插入图片描述


1.3.2 硬链接

  • 我们创建一个普通文件以及一个目录
    在这里插入图片描述

可以发现普通文件的硬链接数是1,而目录一创建出来硬链接数就是2。

  • 我们进入empty目录下

在这里插入图片描述

我们可以看到empty目录下有隐藏的点文件,我们之前讲过,这个就是指的当前目录,它的inode与empty目录的inode是一模一样的,而它就是除了empty外另一个硬链接。

  • 我们进入empty目录下再创建一个a目录

在这里插入图片描述

这里可以看到我们的empty目录的硬链接数变成了3,这就是因为我们empty目录里的a目录里有一个自带的点点文件,这代表的是上级目录,它就是第三个empty目录的硬链接

由此得知:一个目录下有多少个子目录:硬链接数-2即可计算得到

注意:Linux中不允许给目录建立硬链接,但是可以建立软链接


2.动静态库

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

  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码

  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)

  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。


我们是很经常使用库的,我们创建一个普通C文件,并编写简单代码

在这里插入图片描述

这里就是利用了C语言的库的,之前进行简单的讲解过,这是C语言的动态库

在这里插入图片描述


关于库我们有过一定的使用经验
库分为静态库以及动态库-----大部分的系统默认安装的是动态库,云服务器是静态库–(C标准库)默认是没有安装的
默认编译程序,用的是动态链接的,如果要静态要加-static

库的真实名字:lib. XXXX -a/so 去掉前缀以及后缀

2.1 动静态库的制作和使用

一般我们的程序执行会经历几个阶段

  1. a.h + a.c ---> a.o
  2. b.h + b.c ---> b.o
  3. c.h + c.c ---> c.o
  4. d.h + d.c ---> d.o
  5. 再结合libc.so/libc.a
  6. 最后main.c ------>main.o

库则是不提供.c文件

  1. a.h + a.o
  2. b.h + b.o
  3. c.h + c.o
  4. d.h + d.o

你只需要将main.c ------>main.o
注:这里的a、b、c、d只是概念文件

所谓的库就是将所有的.o文件用特定的方式,进行打包,形成一个文件

库的存在的意义:

  1. 提高开发效率
  2. 隐藏源代码

准备工作

在了解库的使用原理后我们来模拟实现一个

  1. 创建五个文件
    在这里插入图片描述
  2. 编写文件

add.c

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

add.h

#ifndef __ADD_H__
#define __ADD_H__ 
int add(int a, int b); 
#endif // __ADD_H__

sub.h

#ifndef __SUB_H__
#define __SUB_H__ 
int sub(int a, int b); 
#endif // __SUB_H

sub.c

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

main.c

#include <stdio.h>
#include "add.h"
#include "sub.h"int main()
{int a = 10;int b = 20;printf("add(%d, %d)=%d\n", a, b, add(a, b));a = 100;b = 20;printf("sub(%d,%d)=%d\n", a, b, sub(a, b));
}

生成.o文件
在这里插入图片描述

生成静态库

指令ar -rc

ar -rc是一个用于创建或更新静态库的命令。它是GNU工具链中的一个工具,用于将一组目标文件打包成一个静态库文件。下面是ar -rc命令的一些常见用法:

  • 创建静态库:可以使用ar -rc命令将多个目标文件打包成一个静态库文件。例如,要将文件1.o、文件2.o和文件3.o打包成一个名为libexample.a的静态库,可以执行以下命令:

ar -rc libexample.a 1.o 2.o 3.o

  • 更新静态库:如果已经存在一个静态库文件,可以使用ar -rc命令向其中添加新的目标文件或替换已有的目标文件。例如,要向名为libexample.a的静态库中添加一个新的目标文件file.o,可以执行以下命令:

ar -rc libexample.a file.o

  • 替换静态库中的目标文件:如果要替换静态库中已有的目标文件,可以使用ar -rc命令指定相同的目标文件名。例如,要替换名为libexample.a的静态库中的目标文件file.o,可以执行以下命令:

ar -rc libexample.a file.o

  • 查看静态库内容:可以使用ar -t命令来查看静态库中包含的目标文件列表。例如,要查看名为libexample.a的静态库中包含的目标文件列表,可以执行以下命令:

ar -t libexample.a


输入指令ar -rc libmymath.a add.o sub.o生成静态库
查看静态库中的目录列表 ar -tv libmymath.a
t:列出静态库中的文件
v:verbose 详细信息

在这里插入图片描述
所以库的本质就是把一堆.o打包形成一个文件,然后通过头文件来调用库。注意,库中不能包含main函数。

编译一下,即可运行

gcc (要形成的可执行文件名) main.c(所依赖的文件) -L .(-L + 路径表示myc这个库在哪个路径下)-lmymath(指明要链接mymath这个静态库)

在这里插入图片描述


生成动态库

fPIC:产生位置无关码,在将.c或者.cpp形成.o文件时,需要加上-fPIC。要形成动态库必须加上-fPIC。
在这里插入图片描述

形成动态库不需要用到其它指令,gcc编译器就可以形成动态库,只不过要加上-shared命令。

gcc -shared -o libmymath.so(名字,真正的库名要去掉lib和.so)sub.o add.o (所依赖的.o文件)

在这里插入图片描述
直接使用我们的这个动态库,那么就同样要告诉编译器我们库的名字和所在的路径(参考上面静态库路径的写法)。

在这里插入图片描述

2.2 将自己的库打包给别人

假设在我当前目录下有libmymath.so动态库,add.h,sub.h两个头文件,如果我想将这三个文件一起交给别人,就可以把它们打包一起放在一个目录下,一起压缩完再交给别人。
在这里插入图片描述

Makefile

 1 libmymath.so:add.o sub.o2     gcc -shared -o $@ $^3 .o:.c4     gcc -shared -c $<5 #add.o:add.c6 #   gcc -c -fPIC $< -o $@7 #sub.o:sub.c8 #   gcc -c -fPIC $< -o $@9 .PHONY:clean10 clean:11   rm -f *.o libmymath.so12 13 .PHONY:output                                                                                                                                                                           14 output:15         mkdir -p ./user/mylib/16         mkdir -p ./user/Headfile/17         cp -rf libmymath.so ./user/mylib/18         cp -rf add.h sub.h ./user/Headfile/19         tar -czf user.tgz user

在这里插入图片描述

user目录是通过user.tgz解压得到的,下面是user目录下的文件:

在这里插入图片描述

将两个头文件拷贝到usr/include目录下(编译器默认会到include目录下去寻找头文件),将库文件拷贝到usr/lib目录下,编译时指定库链接,就能够运行了。
在这里插入图片描述

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

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

相关文章

基于机器学习的人脸发型推荐算法研究与应用实现

1.摘要 本文主要研究内容是开发一种发型推荐系统&#xff0c;旨在识别用户的面部形状&#xff0c;并根据此形状推荐最适合的发型。首先&#xff0c;收集具有各种面部形状的用户照片&#xff0c;并标记它们的脸型&#xff0c;如长形、圆形、椭圆形、心形或方形。接着构建一个面部…

ASP.NET公交车管理系统的实现与设计

摘 要 随着经济的日益增长&#xff0c;信息化时代已经到来&#xff0c;生活中各种信息趋向数字化、清晰化。公交车作为现代城市生活中一种重要的交通工具&#xff0c;其数量增多&#xff0c;车型也不再单一&#xff0c;雇用的司机增多&#xff0c;这样使得公交车公司的车辆信…

HTML重要标签重点及属性(表格表单列表)——之转生在异世界学前端

表格标签 table是用于定义表格的标签 tr是用于定义表格的行 td是用来定义表格的列&#xff0c;th是表头一般只有一个表头会加粗 表格属性border是设置边框值为1;1是有边框&#xff0c; align设置居中对齐方式center&#xff0c;left&#xff0c;right cellpadding设置文字…

ELFK日志分析系统之搭建ELF+Filebeaat+Zookeeper+Kafka

引言 结合前面所学 http://ELK日志分析系统 一、为什么要做日志分析平台 随着业务量的增长&#xff0c;每天业务服务器将会产生上亿条的日志&#xff0c;单个日志文件达几个GB&#xff0c;这时我们发现用Linux自带工具&#xff0c;cat grep awk 分析越来越力不从心了&#…

pixhawk控制板的ArduPilot固件编译

0. 环境 - ubuntu18&#xff08;依赖python2和pip&#xff0c;建议直接ubuntu18不用最新的&#xff09; - pixhawk 2.4.8 - pixhawk 4 1. 获取源码 # 安装git sudo apt install git # 获取源码 cd ~/work git clone --recurse-submodules https://github.com/ArduPilot/a…

分布式ID的方案和架构

超过并发&#xff0c;超高性能分布式ID生成系统的要求 在复杂的超高并发、分布式系统中&#xff0c;往往需要对大量的数据和消息进行唯一标识如在高并发、分布式的金融、支付、餐饮、酒店、电影等产品的系统中&#xff0c;数据日渐增长&#xff0c;对数据分库分表后需要有一个唯…

Java实现二叉树(下)

1.前言 http://t.csdnimg.cn/lO4S7 在前文我们已经简单的讲解了二叉树的基本概念&#xff0c;本文将讲解具体的实现 2.基本功能的实现 2.1获取树中节点个数 public int size(TreeNode root){if(rootnull){return 0;}int retsize(root.left)size(root.right)1;return ret;}p…

【七 (1)FineBI FCP模拟试卷-股票收盘价分析】

目录 文章导航一、字段解释二、需求三、操作步骤1、添加计算字段&#xff08;每月最后一天的收盘价&#xff09;2、绘制折线图 文章导航 【一 简明数据分析进阶路径介绍&#xff08;文章导航&#xff09;】 一、字段解释 Company Name&#xff1a;公司名称 Date&#xff1a;…

计算机网络---第十四天

DHCP协议 DHCP背景&#xff1a; 局域网中手动配置静态ip地址任务繁琐&#xff0c;而且容易出错 DHCP定义&#xff1a; ①动态主机配置协议 ②采用客户端/服务器模式 ③服务端udp 67 ④客户端udp 68 DHCP工作原理&#xff1a; 1、DHCP分配IP的工作流程&#xff1a; 客户…

【opencv】示例-stereo_calib.cpp 基于OpenCV的立体视觉相机校准的完整示例

// 包含OpenCV库中用于3D校准的相关头文件 #include "opencv2/calib3d.hpp" // 包含OpenCV库中用于图像编码解码的相关头文件 #include "opencv2/imgcodecs.hpp" // 包含OpenCV库中用于GUI操作的相关头文件 #include "opencv2/highgui.hpp" // 包…

QT助手翻译【QT 5.14】 -----QPushButton

目录 1 属性 2 公共职能 3 重新实现的公共功能 4 公用插槽 5 受保护的功能 6 保护方法 7 详细说明 1 属性 自动默认值&#xff1a;bool 此属性保存按钮是否为自动默认按钮 如果此属性设置为true&#xff0c;则该按钮为自动默认按钮。 在某些GUI样式中&a…

Linux 快问快答

如果对于找 Java 后端开发的话&#xff0c;我感觉会这几个差不多了&#xff0c;面试官应该不会问的这么详细吧。一般就问问 Linux 的几个常用的命令&#xff0c;然后做一些简单的性能排查就好了。如果面试被问到另外的问题&#xff0c;那我再补充进来&#xff0c;现在先掌握这么…