深入理解 Linux 链接

Windows文件管理中有一个非常实用的功能——快捷方式,它为一份文件提供了多个不同的入口,并以此进行同步。而快捷方式在我看来是对Linux中符号链接功能的一种泛化。(与之类似的,还有MacOS中的别名Alias功能)

在Unix操作系统中,文件的引入使独立于进程之外信息得以长期存储,文件作为进程创建信息的逻辑单元可被多个进程并发使用,简单来说,UNIX 系统中除进程之外的一切皆是文件,Linux 也保持了这一特性, 并引入了目录(文件夹)这一概念便于文件管理。

注:包括键盘鼠标在内的所有设备,依然被操作系统视为文件,并可以被打开进而通讯

Linux的文件数据

Linux将文件数据分为用户数据(user data)与元数据(metadata)两部分,如下图,

Linux将文件数据分为用户数据与文件数据

Linux将文件数据分为用户数据与文件数据

其中文件名(filename)很好理解,而数据块(data blocks)中存储的为文件的具体内容,于此同时,索引节点(inode)则存储了除文件名外的附加属性(文件大小,创建时间,修改时间,所有者,权限等等等等)。同时也很容易理解,对于Linux而言,inode才是文件的唯一标识(我们可以很容易地在不同目录创建同名文件)。

在Linux中可以使用stat <filename>查看Inode编号及属性;或使用 ls -i 列出当前目录下所有文件的 Inode 编号

下面是一个简单的例子,可以看到即使重命名文件并不会改变文件的Inode(Change部分当然除外)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 [email protected]$ stat prime.py  
  File: prime.py 
  Size: 606             Blocks: 8          IO Block: 512    regular file
Device: 2h/2d   Inode: 25614222880720159  Links: 1 
Access: (0666/-rw-rw-rw-)  Uid: ( 1000/ jiachen)   Gid: ( 1000/ jiachen)
Access: 2019-10-04 14:48:59.779690000 +0800
Modify: 2019-10-04 14:48:59.781083800 +0800
Change: 2019-10-04 14:48:59.781083800 +0800
 Birth: -
 [email protected]$ ls -i 
25614222880720159 prime.py 
 [email protected]$ mv prime.py prime.py.test 
 [email protected]$ stat prime.py 
stat: cannot stat 'prime.py': No such file or directory 
[email protected]$ stat prime.py.test  
  File: prime.py.test 
  Size: 606             Blocks: 8          IO Block: 512    regular file
Device: 2h/2d   Inode: 25614222880720159  Links: 1
Access: (0666/-rw-rw-rw-)  Uid: ( 1000/ jiachen)   Gid: ( 1000/ jiachen)
Access: 2019-10-04 14:48:59.779690000 +0800
Modify: 2019-10-04 14:48:59.781083800 +0800
Change: 2019-10-04 14:49:58.919329800 +0800
 Birth: -
 [email protected]$ ls -i
25614222880720159 prime.py.test 

前面已经提到了,既然Linux使用Inode作为文件标识符,那么我们显然可以为其指定不同的入口来进入同一个数据区块。Linux的解决方案是链接,即赋予一个Inode多个文件名。

硬链接与软链接

链接的使用有非常多的优点,例如服务器证书安装中隐藏文件目录,增加安全权限,统一管理等,在目录管理中便于访问,在文件管理中节约存储,保证一致性等。

基于Inode的链接显然只能针对文件使用,为了将其拓展到对于目录的使用,Linux引入了硬链接和软链接两种概念。

软连接硬链接是否支持该特质
NY文件属性必须相同(Inode, datablock)
NY文件必须存在
YN跨文件系统链接
YN链接目录
NN删除链接影响原始文件

以上是软连接与硬链接在表现上的不同,接下来让我们对其实现有一个大概的了解,增强对其表现的认识。

从前面的内容可以得知,硬链接指向了文件的Inode,而软链接显然不能(目录没有)。实际上,软链接严格来说也是文件,只不过它的数据区块存储的是其指向的文件路径,如下所示,

软链接与硬链接对文件的访问

软链接与硬链接对文件的访问

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 [email protected]  ~/tmp  echo "Hello world" >> test 
 [email protected]  ~/tmp  ll 
total 0 
-rw-rw-rw- 1 jiachen jiachen 12 Oct  4 15:16 test
 [email protected]  ~/tmp  cat test          
Hello world 
 [email protected]  ~/tmp  ln -s ~/tmp/test ~/tmp/sln_test  
 [email protected]  ~/tmp  cat sln_test     
Hello world 
 [email protected]  ~/tmp  mv test test_mv 
 [email protected]  ~/tmp  cat sln_test 

很显然,当原始文件的路径改变后,则软连接失效,从前面的例子可以知道硬链接显然不会。

在实际使用中,软连接当然可以链接已有的软链接,但个人不建议这样做,否则容易增加文件系统维护的复杂度。

并且强烈建议使用绝对路径进行链接,以免因为用户切换而造成不可预知的问题。

常用命令

...

Reference: