Linux中的硬链接和软链接

节选自南大蒋炎岩老师操作系统网络课程笔记:(2021) 24 [持久化] 文件系统API

硬(hard)链接

UNIX文件指针

在UNIX中,文件和目录完全不是同一个概念,虽然我们平时看着它们仿佛并列地躺在某个文件夹下。但实际上,目录是树状结构组织的,而文件,却是每个目录指向某个文件的指针。并且,每个文件都有一个编号,可能会有多个目录下的多个指针都指向同一个编号的文件。它们虽然存在于不同的目录下,甚至名称也不同,但是同一个编号的文件是完全相同的,修改也是同步的。如下图所示:

在这里插入图片描述

我们可以做这样的测试:

创建测试目录并在其中的a.txt写入Hello World!

mkdir test && cd test && touch a.txt
vim a.txt # 写入 Hello World!

创建a.txt的硬链接b.txt

ln a.txt b.txt

我们查看两个文件的内容,输出显示都是同样的Hello World:

cat *.txt
# 输出:
# Hello World!
# Hello World!

这时,我们修改b.txt的内容为Hello World! Changed~,再查看两个文件的内容:

vim b.txt		# 更改为 Hello World! Changed~
cat *.txt
# 输出:
# Hello World! Changed~
# Hello World! Changed~

结果两个文件都被修改了,这就是硬链接,我们可以通过-i参数查看文件的编号:

ls -i
# 输出:
# 8593746 a.txt  8593746 b.txt

可以看到,两个文件其实是同一个编号的文件的不同链接。即硬链接的图示如下:在这里插入图片描述

硬链接

注意

  • 目录中仅存储指向文件数据的指针
  • 允许一个文件被多个目录引用
  • 不能链接目录 ❌
  • 不能跨文件系统 ❌

小知识:其实所有的文件都是硬连接 (ls -i 查看)

  • 删除的系统调用称为 “unlink” (引用计数)
应用场景

可以给文件起别名,同步,省空间。

需求:系统中可能有同一个运行库的多个版本

  • libc-2.27.so, libc-2.26.so, …
  • 还需要一个 “当前版本的 libc”
    • 程序需要链接 “libc.so.6
    • 能否避免文件的一份拷贝?

软(symbolic)链接

软链接:在文件里存储一个 “跳转提示”,相当于”快捷方式“。

  • 软链接也是一个文件
    • 当引用这个文件时,去找另一个文件
    • 另一个文件的绝对/相对路径以文本形式存储在文件里
    • 可以跨文件系统、可以链接目录、……好处多多
    • 甚至,符号链接可以指向一个暂时不存在的文件或目录,只要这个不存在文件或目录将来某天存在了,这个符号链接就会生效

ln -s 创建软链接,用的是symlink 系统调用。现在系统中/lib下的共享库,通常都是软链接。

我们接着上面硬链接的例子来看一下二者的区别:

再在测试目录下创建a.txt的软链接c.txt

ln -s a.txt c.txt

我们用-li参数查看测试目录中的三个文件:

ls -li
# 输出
# 8593746 -rw-rw-r-- 2 ps ps 22 10月  1 22:14 a.txt
# 8593746 -rw-rw-r-- 2 ps ps 22 10月  1 22:14 b.txt
# 8593742 lrwxrwxrwx 1 ps ps  5 10月  1 22:35 c.txt -> a.txt

在这里,b,c分别是a的硬、软链接。可以看到,a和c的文件编号是不一样的,因为它们是软链接,并且可以看到,c作为a的软链接,会有一个箭头指向a。但是,它们的修改仍然是同步的,因为我们在试图修改c的时候,系统会顺着上面输出的软链接箭头去寻找,直到找到一个真实的文件或者目录。我们还是来试一下:

vim c.txt # 修改为Hello World! Changed~ Soft~
cat *.txt
# 输出:
# Hello World! Changed~ Soft~
# Hello World! Changed~ Soft~
# Hello World! Changed~ Soft~

与预期一致。此时测试目录下的链接关系应该如下图所示:
在这里插入图片描述

软链接可能带来的麻烦

软链接可以随意创建 (当前可能不合法;但未来可能合法),操作系统在处理软链接时会执行路径解析,,允许多次间接链接,会有意想不到的复杂性 ,a → b → c (递归解析)。可以创建软连接的硬链接 (因为软链接也是文件),通过ls -i 可以看到。

符号链接成环?ln -s . a。所有处理符号链接的程序 (tree, find, …) 都要考虑递归的情况。它们默认遇到软链接就跳过,如果加上-L参数强制使它们考虑软链接的话,它们也会很小心的检测成环和递归的情况并适时退出。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐