Linux 之 符號鏈接與硬鏈接


鏈接簡單理解就是,添加一個對文件/文件夾的訪問副本,更方便平時的一些操作。類比Windows的快捷方式。

簡單先看一下符號鏈接與硬鏈接的生成與使用。

生成符號鏈接與硬鏈接

  • 創建符號鏈接:ln -s target_file link_file

  • 創建硬鏈接:ln target_file link_file

演示:

創建文件的符號鏈接

$ ln -s file1 file_symlink

創建文件的硬鏈接

$ ln file1 file_hardlink

創建文件夾的符號鏈接

$ ln -s link_test_dir dir_symlink

創建文件夾的硬鏈接:創建失敗

$ ln -s link_test_dir dir_hardlink
ln: link_test_dir: hard link not allowed for directory

從上面的流程和截圖的觀察中,可以總結幾點:

  • 在表現形式上(ls -alh查看):
    • 符號鏈接表現為指向被鏈接文件的形式,硬鏈接表現為單獨的文件。
    • 符號鏈接權限為lrwxrwxrwx.,硬鏈接權限與源文件一致
    • 硬鏈接大小與源文件一致,符號鏈接大小為被鏈接文件的路徑字符長度
  • 硬鏈接不允許創建給目錄,符號鏈接可以。
  • 訪問文件:都是源文件的值

做一些操作,再觀察現象:

  • 修改權限

    • 修改硬鏈接權限

    • 修改軟連接權限

  • 修改屬主

    • 修改硬鏈接屬主

    • 修改軟連接權限

  • 刪除源文件后,再訪問符號鏈接和硬鏈接

總結以上情況,我們可以再補充一些符號鏈接跟硬鏈接的特點:

  • 訪問符號鏈接和硬鏈接實際都是訪問被鏈接文件;
  • 硬鏈接修改權限/屬主時,源文件跟着一起變;符號鏈接修改權限/屬主時,鏈接文件未變化,實際變化的是源文件,且硬鏈接文件的屬性跟着一起變動;
  • 源文件被刪除時,硬鏈接文件仍然可以訪問,且與源文件一致;訪問符號鏈接文件時會找不到對象。

按上面的操作,基本可以運用符號鏈接和軟連接。但是留有一些疑問:

  • 為什么源文件刪除了,硬鏈接還能正常訪問,而符號鏈接卻失效了?
  • 為什么修改符號鏈接的屬主/權限,符號鏈接的屬主/權限卻未變動,變動的是源文件?
  • 為什么硬鏈接的所有文件屬性都跟源文件保持一致?
  • 為什么硬鏈接不能鏈接給目錄?

要解答這些問題,可以先延伸看下Linux文件系統的管理模式。

Linux文件管理

當我們使用Linux文件系統時,文件系統通常會將文件的兩部分數據分別放在不同的區塊中:權限與屬性放置在inode中,實際數據放置在data block中。另外,還有一個超級區塊 (superblock) 會記錄整個文件系統的整體信息,包括 inode 與 block 的總量、使用量、剩余量等。

每個 inode 與 block 都有編號,這三個數據:

  • superblock:記錄所在 filesystem 的整體信息,包括inode/block的總量、使用量、剩余量,以及文件系統的格式與相關信息等;
  • inode:記錄文件的屬性,一個文件占用一個inode,同時記錄此文件的數據所在的 block號碼;
  • block:實際記錄文件的內容,若文件太大時,會占用多個 block 。

這種數據存取的方法我們稱為索引式文件系統(indexed allocation)

當我們在 Linux 下的文件系統創建一個目錄時,文件系統會分配一個 inode 與至少一塊 block給該目錄。其中,inode 記錄該目錄的相關權限與屬性,並可記錄分配到的那塊 block 號碼;而 block 則是記錄在這個目錄下的文件名與該文件名占用的 inode 號碼數據

文件尋址過程

整個文件系統的目錄結構就如一個樹狀圖,從根目錄開始,從目錄的inode獲取它的block。從block中獲取子目錄的inode值,持續往下尋址直到找到對應文件。

以上一節的源文件/home/jingx/test_link_dir/file1為例,文件系統訪問這個文件的流程如下:

  1. 找到"/"掛載點,獲取root inode。

PS:在往下搜尋的時候,如果有新的掛載點,會重新獲取root inode。當前僅討論簡單情況。

  1. 通過root inode找到對應block,繼續往下尋找下一個目錄的inode。通過inode獲取文件權限屬性,check當前用戶的操作是否有權限繼續;如果有權限,則通過inode指向的block搜尋下一層,直到搜索到最終文件:home/jingx/test_link_dir/file1。

  2. 最終找到對應文件的inode,從inode中獲取文件屬性和block號;從block號獲取文件內容。這就是一次完整的文件尋址過程。

硬鏈接實現

從上一節知道了文件的尋址過程。現在來看硬鏈接的具體實現方式:

  • 硬鏈接某一個文件時,實際上是在對應父目錄的block中,添加一條 inode:硬鏈接文件名 的記錄。通過ls -il命令可以輸出對應文件的inode號。可以看到源文件和硬鏈接文件,其實是同一個inode號

如果硬鏈接文件在其他目錄,也是同樣在對應目錄的block中添加一條指向文件實際inode的記錄。

同時觀察輸出的第三列屬性,因為當前有3個對象指向這個inode,所以這個inode的引用為3。

PS:直到inode引用為0時,這個文件才從文件系統認定被刪除。

所以建立文件的硬鏈接,實際上就是在對應目錄的block中新建一條記錄,並非新增一個文件

符號鏈接

對比硬鏈接的實現,符號鏈接實際上是一個真實存在的文件。

  • 它是一個跟普通文件一樣,存在於硬盤中,有自己的inode編號和block。

  • inode中標明它的文件類型是符號鏈接(權限中的第一位l);

  • 顯示權限為777,但實際權限是跟父目錄及被鏈接對象有關:

    • 如果是對符號鏈接本身的操作(刪除或修改指向),則根據操作用戶在父目錄的權限來執行;

    • 如果是對符號鏈接指向對象的操作(chmod、chown、cp等),則根據操作用戶在被鏈接對象的權限來執行;

  • 符號鏈接文件實體內容則只有被鏈接文件的路徑。存儲位置根據鏈接格式(local、extend)有關,在此不贅述;

遺留問題回答

根據上面描述的硬鏈接和符號鏈接的特點,可以回溯文章開始提出的一些問題:

  • 為什么源文件刪除了,硬鏈接還能正常訪問,而符號鏈接卻失效了?

    因為刪除源文件的操作,實際上是在它父目錄的block中刪掉類似對應的 文件名:inode 的指向。實際的文件內容(inode、block)並沒有刪掉。硬鏈接還可以根據本身的inode號進行文件尋址。而符號鏈接實際保存的是源文件的路徑,所以訪問符號鏈接時候,會根據路徑去尋找文件。而源文件刪除后,該路徑的文件記錄已經不存在了,所以會導致No such file or directory

  • 為什么修改符號鏈接的屬主/權限,符號鏈接的屬主/權限卻未變動,變動的是源文件?

    因為像chmod/chown等命令做操作的時候,會遞歸的去對最終文件進行操作。所以修改屬主/權限的操作實際是針對源文件的。

    因為這個原因,導致了符號鏈接的提權類問題。由於操作、符號鏈接所在目錄、源文件三者的權限不一致,可能導致通過偽造符號鏈接等方式進行提權操作。如果添加"-h"參數,則會在操作的時候忽略符號鏈接文件。以此來防止

  • 為什么硬鏈接的所有文件屬性都跟源文件保持一致?

    因為硬鏈接文件的inode和源文件的inode是同一個,而inode是存儲文件屬性的位置。

  • 為什么硬鏈接不能鏈接給目錄?

    為了防止路徑回環。回憶之前說的文件尋址模式,是通過樹狀來進行尋址。假設將/a/b/hardlink_dir鏈接到/a上,由於a和hardlink_dir都是同一個inode,在尋址邏輯上會變成hardlink_dir既是b的子目錄又是b的父目錄(a)。在內核的處理上復雜度變變的更高,所以從使用工具層面上禁止了目錄的硬鏈接。

    PS:在系統中實際是存在兩個特殊的硬鏈接,即:....指向目錄本身,..指向父目錄。因為系統對它們做了特殊處理,所以不會有路徑回環的問題發生。

  • 補充:硬鏈接也不能跨文件系統進行鏈接,因為尋址模式、inode存儲方式以及superblock在不同的文件系統間是不一樣的。而軟鏈接可以跨文件系統鏈接,因為軟鏈接只存儲被鏈接文件的路徑,根據路徑進行尋址這個是文件系統的共性。

Reference

linux創建的硬鏈接為什么不占用磁盤空間?

Linux系統如何知道某文件在硬盤中的位置?

XFS的on-disk組織結構(13)——Inode datafork of symlink file

linux為什么不能硬鏈接目錄?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM