淺談Linux軟硬鏈接的聯繫和區別

1. 前言

前天因爲在centOS7在命令行使用vim命令報錯bash: vim: command not found on CentOS 7,Google後發現,可以root權限下,通過ln -s /usr/bin/vi /usr/bin/vim建立軟鏈接解決這個問題。
因此就想了解一下軟硬鏈接的區別,便看了幾篇博客,有些博客講的比較繞,看完一臉懵圈,有些寫的很透徹,於是想把看到的好博客進行總結,一方面利於日後查看,另一方面也希望能幫助和我一樣的小白,少走一些彎路。

2. Linux文件系統中的文件、inode、文件名和目錄

爲了更好地理解軟硬鏈接,需要先簡單的瞭解Linux中文件、inode、文件名和目錄的概念。
現代操作系統爲解決信息能獨立於進程之外被長期存儲引入了文件,文件作爲進程創建信息的邏輯單元可被多個進程併發使用。
文件Linux系統中,除進程之外的一切皆是文件。文件都有文件名與數據,這在 Linux 上被分成兩個部分:用戶數據 (user data) 與元數據 (metadata)。用戶數據,即文件數據塊 (data block),數據塊是記錄文件真實內容的地方;而元數據則是文件的附加屬性,比如創建時間、修改時間、文件大小、屬主、歸屬的用戶組、讀寫權限、數據所在block號等。
inode:在Linux的文件系統中,保存在磁盤分區中的文件,不管是什麼類型都會給它分配一個編號,這個編號被稱爲索引節點編號(inode index)或者inode。inode 是文件元數據的一部分,但其並不包含文件名。在 Linux ,元數據中的 inode 號是文件在一個文件系統中的唯一標識,不同文件系統inode號可以相同。系統或程序通過 inode 號尋找正確的文件數據塊,而不是文件名。換句話說,操作系統只認inode號,不認文件名,文件名是方便人類而存在的。
文件名:文件名僅是爲了方便人們的記憶和使用,相當於給inode號起了一個人類便於記憶和使用的名字。
目錄:目錄是特殊的文件,是記錄了其他文件名的文件。引入目錄的原因是爲了便於Linux管理文件,目錄有時也被稱爲文件夾。目錄使文件可被分類管理,且目錄的引入使 Linux 的文件系統形成一個層級結構的目錄樹。實際上,Linux 與其他類 UNIX 系統一樣,並不區分文件與目錄。使用命令 mkdir 創建目錄時,若期望創建的目錄的名稱與現有的文件名(或目錄名)重複,則會創建失敗。
下圖是Linux 系統的頂層目錄結構

/ 根目錄
├── bin 存放用戶二進制文件
├── boot 存放內核引導配置文件
├── dev 存放設備文件
├── etc 存放系統配置文件
├── home 用戶主目錄
├── lib 動態共享庫
├── lost+found 文件系統恢復時的恢復文件
├── media 可卸載存儲介質掛載點
├── mnt 文件系統臨時掛載點
├── opt 附加的應用程序包
├── proc 系統內存的映射目錄,提供內核與進程信息
├── root root 用戶主目錄
├── sbin 存放系統二進制文件
├── srv 存放服務相關數據
├── sys sys 虛擬文件系統掛載點
├── tmp 存放臨時文件
├── usr 存放用戶應用程序
└── var 存放郵件、系統日誌等變化文件

下圖展示了程序通過文件名獲取文件內容的過程。
在這裏插入圖片描述

3. 什麼是硬鏈接和軟鏈接?

硬鏈接(Hard Link):在Linux系統中,多個文件名指向同一索引節點(Inode)是正常且允許的。一般這種鏈接就稱爲硬鏈接。
軟鏈接(又稱符號鏈接,即 soft link 或 symbolic link):類似於windows系統中的快捷方式,與硬鏈接不同,軟鏈接就是一個普通文件,只是數據塊內容有點特殊,文件用戶數據塊中存放的內容是另一文件的路徑名的指向,通過這個方式可以快速定位到軟連接所指向的源文件實體。軟鏈接可對文件或目錄創建。

4. 建立軟硬鏈接語法

ln命令格式:
ln [參數] [源文件或目錄] [目標文件或目錄]
主要參數:
-i 交互模式,文件存在則提示用戶是否覆蓋。
-s 軟鏈接(符號鏈接)。
-d 允許超級用戶製作目錄的硬鏈接。
-b 刪除,覆蓋以前建立的鏈接
軟鏈接(symbolic link) :ln -s 源文件 目標文件
硬鏈接(hard link) :ln 源文件 目標文件
源文件:即你要對誰建立鏈接

5. 軟硬鏈接的區別和聯繫

爲了便於說明,我這裏在/tmp目錄下新建了text.txt文件。
在這裏插入圖片描述
往test.txt文件中寫入I love Java
在這裏插入圖片描述
分別創建軟硬鏈接以及分別用cp命令複製爲test_cp1.txt和cp -p命令複製爲text_cp2.txt。注:cp -p命令還會複製文件的創建時間等屬性。查看相關文件信息如下:
在這裏插入圖片描述
可以發現:

  1. 軟鏈接的文件test_soft.txt大小隻有8,它的數據部分僅包含它所要鏈接文件的路徑名,所以相對較小,創建時間也和源文件test.txt創建時間不同。
  2. 硬鏈接的文件test.hard.txt文件大小、創建時間都和源文件相同。手誤,本來想命名爲test_hard.txt的。
  3. cp 命令複製的文件test_cp1.txt文件大小和源文件相同,但是創建時間不同。
  4. cp -p命令複製的文件test_cp2.txt文件大小和創建時間都和源文件相同。
    繼續查看各文件的inode,使用ls -i命令。
    在這裏插入圖片描述
    可以看到,只有建立硬鏈接時,得到的inode和源文件相同,複製或者軟鏈接都會得到新的inode。
    那麼我們修改一下源文件,往test.txt裏面追加I love Python.。看看其他的軟硬鏈接文件和複製文件會有什麼變化?
    在這裏插入圖片描述
    複製的兩個文件都沒有被更新,可以看到軟硬鏈接文件的內容都被更新了,並且硬鏈接的文件時間和源文件進行了同步,但是軟鏈接文件的文件時間沒有同步更新。
    那麼,我們想一下,如果我更改硬鏈接文件,那麼源文件和軟鏈接文件會不會變呢?
    往test.hard.txt文件中寫入I love C.,然後查看各文件信息和inode。
    在這裏插入圖片描述
    可以看到改變硬鏈接文件的效果和改變源文件的效果是一樣的。綜上我們可以分析得出,硬鏈接和源文件共享一個inode,每建立一個硬鏈接,就在inode的硬鏈接數(i_nlink)上+1,同理每刪除一個硬鏈接,就在inode的硬鏈接數(i_nlink)上-1,如果inode的i_nlink計數爲0,操作系統就會回收inode指向的存儲空間,此時如果有新數據要存儲到磁盤上,被刪除的文件的數據塊及目錄的鏈接纔會被釋放,空間被新數據暫用覆蓋。注意:這裏的源文件test.txt也不過是一個符號而已,inode纔是Linux真正識別的
    從而我們可以推斷出,如果我們刪除源文件test.txt,那麼軟鏈接文件讀不到源文件了,從而報錯,因爲軟鏈接文件保存的是源文件的路徑信息,但是硬鏈接文件還在,只是inode硬鏈接數(i_nlink)-1。
    在這裏插入圖片描述
    軟硬鏈接的訪問如下圖:
    在這裏插入圖片描述

6. 軟硬鏈接的作用及應用場景

爲解決文件的共享使用,Linux 系統引入了兩種鏈接:硬鏈接 (hard link) 與軟鏈接(又稱符號鏈接,即 soft link 或 symbolic link)。鏈接爲 Linux 系統解決了文件的共享使用,還帶來了隱藏文件路徑、增加權限安全及節省存儲等好處。

6.1 硬鏈接的作用

  1. 允許一個文件擁有多個有效路徑名,對重要的文件建立硬鏈接,以防止“誤刪”源數據(很多硬件,如netapp存儲中的快照功能就應用了這個原理,增加一個快照就多了一個硬鏈接)。
  2. 實現在一個文件系統內的文件共享,解決存儲空間。

6.2 軟鏈接的作用

軟鏈接的存在是爲了解決硬鏈接存在的兩個缺點:1)不能對目錄進行鏈接;2)不能跨文件系統進行了鏈接。

  1. 便於文件的管理。比如把一個複雜路徑下的文件鏈接到一個簡單路徑下方便用戶訪問,類似於windows下的桌面快捷鍵方式。
  2. 節省空間解決空間不足問題。因爲軟鏈接可以跨文件系統,所以當某個文件文件系統空間已經用完了,但是現在必須在該文件系統下,創建一個新的目錄並存儲大量的文件時,那麼可以把另一個剩餘空間較多的文件系統中的目錄鏈接到該文件系統中。

7. 小結

硬鏈接相當於給文件取別名,inode不變;軟鏈接類似於windows下的快捷鍵,對文件的一個名字進行了映射,有自己的inode。

7.1 硬鏈接特性

  1. 文件有相同的 inode 及 data block;
  2. 只能對已存在的文件進行創建;
  3. 不能交叉文件系統進行硬鏈接的創建;
  4. 不能對目錄進行創建,只可對文件創建;
  5. 刪除一個硬鏈接文件並不影響其他有相同 inode 號的文件。
# ls -li 
total 0 
 
// 只能對已存在的文件創建硬連接
# link old.file hard.link 
link: cannot create link `hard.link' to `old.file': No such file or directory 
 
# echo "This is an original file" > old.file 
# cat old.file 
This is an original file 
# stat old.file 
 File: `old.file'
 Size: 25 Blocks: 8 IO Block: 4096 regular file 
Device: 807h/2055d Inode: 660650 Links: 2 
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) 
... 
// 文件有相同的 inode 號以及 data block 
# link old.file hard.link | ls -li 
total 8 
660650 -rw-r--r-- 2 root root 25 Sep 1 17:44 hard.link 
660650 -rw-r--r-- 2 root root 25 Sep 1 17:44 old.file 
 
// 不能交叉文件系統
# ln /dev/input/event5 /root/bfile.txt 
ln: failed to create hard link `/root/bfile.txt' => `/dev/input/event5': 
Invalid cross-device link 
 
// 不能對目錄進行創建硬連接
# mkdir -p old.dir/test 
# ln old.dir/ hardlink.dir 
ln: `old.dir/': hard link not allowed for directory 
# ls -iF 
660650 hard.link 657948 old.dir/ 660650 old.file

7.2 軟鏈接特性

  1. 軟鏈接有自己的文件屬性及權限等;
  2. 可對不存在的文件或目錄創建軟鏈接;
  3. 軟鏈接可交叉文件系統;
  4. 軟鏈接可對文件或目錄創建;
  5. 創建軟鏈接時,鏈接計數 i_nlink 不會增加;
  6. 刪除軟鏈接並不影響被指向的文件,但若被指向的原文件被刪除,則相關軟連接被稱爲死鏈接(即 dangling link,若被指向路徑文件被重新創建,死鏈接可恢復爲正常的軟鏈接)。
# ls -li 
 total 0 
 
 // 可對不存在的文件創建軟鏈接
 # ln -s old.file soft.link 
 # ls -liF 
 total 0 
 789467 lrwxrwxrwx 1 root root 8 Sep 1 18:00 soft.link -> old.file 
 
 // 由於被指向的文件不存在,此時的軟鏈接 soft.link 就是死鏈接
 # cat soft.link 
 cat: soft.link: No such file or directory 
 
 // 創建被指向的文件 old.file,soft.link 恢復成正常的軟鏈接
 # echo "This is an original file_A" >> old.file 
 # cat soft.link 
 This is an original file_A 
 
 // 對不存在的目錄創建軟鏈接
 # ln -s old.dir soft.link.dir 
 # mkdir -p old.dir/test 
 # tree . -F --inodes 
 . 
├── [ 789497] old.dir/ 
│ └── [ 789498] test/ 
├── [ 789495] old.file 
├── [ 789495] soft.link -> old.file 
└── [ 789497] soft.link.dir -> old.dir/

不論是硬鏈接或軟鏈接都不會將原本的檔案複製一份,只會佔用非常少量的磁盤空間。
以上相關特性的實際代碼來自參考文獻3。

8. 參考文獻

站在巨人的肩膀上能夠幫助我們少走彎路。
1 適合初步瞭解軟硬鏈接,以及它們和複製的區別;
2 相對專業的介紹了軟硬鏈接在操作系統中的實現以及意義;
3 這位大神寫的非常好,幫助我們更加深入地去理解軟硬鏈接,尤其是裏面的inode和Linux文件系統,非常全面和深入,可以按照這個順序把三篇博客看完,基本就對軟硬鏈接有個基本的掌握了。

  1. 軟鏈接和硬鏈接到底有啥作用和區別
  2. Linux系統硬鏈接和軟鏈接
  3. 理解 Linux 的硬鏈接與軟鏈接
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章