背景
为什么我想研究这个呢!起先是我是我在研究nvm
的时候,发现了符号连接这个东西。符号连接可以说是nvm
实现版本切换的核心。在研究pnpm
的时候,又发现pnpm
对依赖树的处理也使用了硬连接和符号连接相结合的方式。对此,我对他俩产生了浓厚的兴趣,确实是我的知识盲区。
初识硬连接和符号连接
硬连接(hard link
)和符号连接(symbolic link
)在很多操作系统中都存在,他们由文件系统实现和支持,他们底层的实现原理可能存在大同小异,但是具体表现都是相同的。最初出现这个概念应该是在linux
系统。但本文主要分析**windows**
系统下硬连接和符号连接的实现。
硬连接
**其实文件管理器中的任何文件都是硬连接。**
这样一说的话,我感觉大家都蒙了。为什么,其实我感觉我们需要重新认识一下**文件**
这个概念了。
重新认识文件
我们知道,我们是通过硬盘储存我们的文件,所以我们可能很容易的想当然认为文件就会像打开C盘那样的图像化界面一样放在C盘内。显然不是这样的,计算机的世界里只存在二进制,所以文件肯定是以二进制的形式存放在硬盘的某个位置。
比如我们存储一个
**demo.txt**
文件,这个时候文件系统就会生成一个文件ID,和我们存储的数据(比如这个**demo.txt**
)进行一个一对一的绑定。文件ID在同一个卷中是唯一的。 但是,直到现在好像也没有图形化界面中那个可以点击的**demo.txt**
什么事儿!下面关系就来了,文件ID和文件路径存在一个一对多的联系的。 当你新建一个**demo.txt**
文件的时候,文件系统会在硬盘的一个区域写入这个文件,并且给这个区域分配一个文件ID,同时将**demo.txt**
的路径和文件ID对应上。这样通过这个路径我们就可以定位到文件ID,从而定位到真正储存的数据了!!! 这个路径,对应的其实就是一个硬连接!!!所以我们常说的文件,其实就是一个硬连接。
我们可以通过系统内置的查找文件硬连接列表的命令印证自己想法:**fsutil hardlink list [文件路径]**
所以我们常说的文件其实就是一个硬连接。
硬连接的特性
其实从我们之前的描述,也能推断出硬连接存在哪些特性。
- 硬连接是和文件ID形成对应关系的,而文件ID只会在一个卷中才会是唯一的。(硬盘储存文件,是硬盘切割成卷来储存数据,文件系统赋予了数据同卷下独一无二的文件ID,关于卷和盘符的概念和区别,我还是很模糊。) 所以硬连接和他指向的文件是在同一个卷下的。并且没人可以在一个卷中编辑另一个卷。(这里可以简单理解为硬连接只能指向同盘符下的文件。)
- 文件ID和硬连接是一对多的关系的,但是至多1023个硬连接。
- 不可以为目录创建硬连接,这样的话,目录的子文件的父亲就不会唯一。这会导致问题的。
- 由于各个硬连接指向的文件ID是一致的,也就是数据是一致的,可以将硬连接理解成指针,所以从一个硬连接编辑文件,从另一个硬连接也会看到改变。所以也侧面反应,无论创建多少个硬连接,最终数据占据的空间是不会变的,因为始终只有一份数据。
- 当删除硬连接时,如果数据还存在其他硬连接,换句话说,如果文件ID还有文件路径与之对应,那么这个数据就还能被访问到,那么它就不能被删除。反之,如果这个文件ID不存在与之对应的文件路径。那么这个数据就会被真正移除。这个其实就是文件系统维护的一个引用计数,不存在引用了,说明他就能被回收(删除)了。这个跟javascript中垃圾回收机制的一种方案,引用计数道理是一致的。
- 移动硬连接或者改变硬连接的名称并不会导致硬连接的连接失效。
硬连接的创建
硬连接的创建,其实不像新建普通文件那样简单。存在两种方式:
- 通过命令行创建硬连接。
- 通过
link shell extension
创建硬连接。通过命令行创建硬连接
New-Item [硬连接的名称] -ItemType HardLink -Target [目标文件的绝对路径]
执行命令:New-Item hardlink.txt -ItemType HardLink -Target demo.txt
怎么证实他们指向同一个文件ID呢?
我们可以使用命令行命令判断,指定文件路径指向哪个文件ID:fsutil file queryFileID [文件路径]
通过link shell extension创建硬连接
[link shell extension](https://schinagl.priv.at/nt/hardlinkshellext/hardlinkshellext.html)
是一个强大的符号连接和硬连接的新建和管理工具。使用方法一共两种,第一种使用鼠标中键将目标文件拖拽到想要新建硬连接的文件夹: 第二种,是右键目标文件点击”选择源连接点”,然后在新建硬连接的文件夹继续右键点击”创建为…” 这个工具还会为硬连接添加一些实用选项卡:
我们可以在这个“连接属性”中获取几个关键信息:引用计数和文件ID与之对应的文件路径列表。符号连接
符号连接,符号连接跟硬连接存在本质的不同,符号连接实际上和快捷方式有点类似。符号连接的主要原理是这样的:符号连接本身和一个数据对应,或者说他对应一个内存区域(文件ID),这个内存区域其实储存的就是一个路径。然后文件系统就会去访问这个路径对应的资源。
所以,从这点描述上我们就可以知道,符号连接对应的文件ID和目标文件的文件ID肯定是不同的。符号连接的文件ID对应的内存区域储存目标文件的文件路径,而目标文件的文件ID对应的储存区域储存目标文件。
所以,我们生成符号连接的时候,必须要提供一个文件路径。
符号连接的特性
- 符号连接可以指向任何文件或者文件夹,因为符号连接指向的内存区域当然可以存储任何路径了!文件路径,文件夹路径,甚至可以给他提供一个不存在路径。
- 对符号连接连接的文件做的任何操作都是会作用到目标文件上的,因为操作的就是目标文件本身
- 对目标文件进行移动,改名会使得符号连接的连接失效,这也是容易理解的,当做了如上操作之后,符号连接指向的内存区域储存的路径自然是一个错误的路径了。
- 对符号连接进行删除,并不会影响目标文件,影响的反而是符号连接本身。这样的话,导致符号连接指向的内存区域由于没有被任何文件路径引用,而被删除。
创建符号连接
通过命令行创建符号连接
New-Item [软连接的名称] -ItemType SymbolicLink -Target [目标文件的绝对路径]
符号连接的创建需要开启管理员权限!!!通过link shell extension创建符号连接
过程同硬连接的创建
同样的这个工具也给符号连接提供了有用的信息展示项,记录了连接的目标:
符号连接和快捷方式的区别
其实,符号连接和快捷方式有很多相似的地方。比如说,他们都有目标路径,他们的删除都对目标不会产生任何影响。但是他们存在些许的不同。快捷方式本质上是一个文件,后缀名以
.lnk
结尾。这个文件储存了目标文件的路径,所以他本身具有一定大小。 符号连接并不局限于以某个特定的后缀名结尾,符号连接可以是.txt
,.docx
,都有可能。本身是不具备大小的。 此外,快捷方式必须使用绝对路径,而符号连接可以使用相对路径和绝对路径。
给符号连接创建硬连接
突然灵光一现,我想给符号连接创建一个硬连接会导致什么样的情况。
这种情况下,不会创建出硬链接,而会创建出一个符号连接:
并且他们指向的内存数据是一致的。
软连接
其实,在别的文件系统中,软连接和符号连接(
symbolic link
)是一个概念,但是在windows
的文件系统中,他们是不一样的概念。因为在windows
引入symbolic link
之前出现过一种和symbolic link
的功能十分类似的连接,他的名字叫junctions
。所以他就先入为主的称为了软连接(soft link
)。
windows中的连接种类 | 中文名字 |
---|---|
junctions | 软连接(又称目录连接) |
symbolic link | 符号连接 |
hard link | 硬连接 |
其实,windows
的软连接和符号连接,从原理和表现上看都是非常类似的。(软连接同样可以跨卷)主要区别可能是这几点: