Linux ln命令:在文件之間建立鏈接(硬鏈接和軟鏈接)詳解版


如果要想說清楚 ln 命令,則必須先解釋下 ext 文件系統(Linux 文件系統)是如何工作的。我們在前面講解了分區的格式化就是寫入文件系統,而我們的 Linux 目前使用的是 ext4 文件系統。如果用一張示意圖來描述 ext4 文件系統,則可以參考圖 1。


ext4 文件系統示意圖
圖 1 ext4 文件系統示意圖


ext4 文件系統會把分區主要分為兩大部分(暫時不提超級塊):小部分用於保存文件的 inode (i 節點)信息;剩余的大部分用於保存 block 信息。

inode 的默認大小為 128 Byte,用來記錄文件的權限(r、w、x)、文件的所有者和屬組、文件的大小、文件的狀態改變時間(ctime)、文件的最近一次讀取時間(atime)、文件的最近一次修改時間(mtime)、文件的數據真正保存的 block 編號。每個文件需要占用一個 inode。大家如果仔細查看,就會發現 inode 中是不記錄文件名的,那是因為文件名記錄在文件所在目錄的 block 中。

block 的大小可以是 1KB、2KB、4KB,默認為 4KB。block 用於實際的數據存儲,如果一個 block 放不下數據,則可以占用多個 block。例如,有一個 10KB 的文件需要存儲,則會占用 3 個 block,雖然最后一個 block 不能占滿,但也不能再放入其他文件的數據。這 3 個 block 有可能是連續的,也有可能是分散的。

由此,我們可以知道以下 2 個重要的信息:

  1. 每個文件都獨自占用一個 inode,文件內容由 inode 的記錄來指向;
  2. 如果想要讀取文件內容,就必須借助目錄中記錄的文件名找到該文件的 inode,才能成功找到文件內容所在的 block 塊;


了解了 Linux 系統底層文件的存儲狀態后,接下來學習 ln 命令。

ln 命令用於給文件創建鏈接,根據 Linux 系統存儲文件的特點,鏈接的方式分為以下 2 種:

  • 軟鏈接:類似於 Windows 系統中給文件創建快捷方式,即產生一個特殊的文件,該文件用來指向另一個文件,此鏈接方式同樣適用於目錄。
  • 硬鏈接:我們知道,文件的基本信息都存儲在 inode 中,而硬鏈接指的就是給一個文件的 inode 分配多個文件名,通過任何一個文件名,都可以找到此文件的 inode,從而讀取該文件的數據信息。


ln 命令的基本格式如下:

[root@localhost ~]# ln [選項] 源文件 目標文件

選項:

  • -s:建立軟鏈接文件。如果不加 "-s" 選項,則建立硬鏈接文件;
  • -f:強制。如果目標文件已經存在,則刪除目標文件后再建立鏈接文件;


【例 1】創建硬鏈接:

[root@localhost ~]# touch cangls
[root@localhost ~]# ln /root/cangls /tmp
#建立硬鏈接文件,目標文件沒有寫文件名,會和原名一致
#也就是/tmp/cangls 是硬鏈接文件


【例 2】創建軟鏈接:

[root@localhost ~]# touch bols
[root@localhost ~]# In -s /root/bols /tmp
#建立軟鏈接文件

這里需要注意,軟鏈接文件的源文件必須寫成絕對路徑,而不能寫成相對路徑(硬鏈接沒有這樣的要求);否則軟鏈接文件會報錯。這是初學者非常容易犯的錯誤。

ln創建鏈接的深度剖析

建立硬鏈接和軟鏈接非常簡單,那這兩種鏈接有什么區別?它們都有什么作用?這才是鏈接文件最不容易理解的地方,我們分別來講講。

ln創建硬鏈接

我們再來建立一個硬鏈接文件,然后看看這兩個文件的特點。

[root@localhost ~]# touch test
#建立源文件
[root@localhost ~]# ln /root/test /tmp/test-hard
#給源文件建立硬鏈接文件 /tmp/test-hard
[root@localhost ~]# ll -i /root/test /tmp/test-hard
262147 -rw-r--r-- 2 root root 0 6月 19 10:06 /root/test
hard
262147 -rw-r--r-- 2 root root 0 6月 19 10:06 /tmp/test-hard
#查看兩個文件的詳細信息,可以發現這兩個文件的 inode 號是一樣的,"ll"等同於"ls -l"。

這里有一件很奇怪的事情,我們之前在講 inode 號的時候說過,每個文件的 inode 號都應該是不一樣的。inode 號就相當於文件 ID,我們在查找文件的時候,要先查找 inode 號,才能讀取到文件的內容。

但是這里源文件和硬鏈接文件的 inode 號居然是一樣的,那我們在查找文件的時候,到底找到的是哪一個文件呢?我們來畫一張示意圖,如圖 2 所示。


硬鏈接示意圖
圖 2 硬鏈接示意圖


在 inode 信息中,是不會記錄文件名稱的,而是把文件名記錄在上級目錄的 block 中。也就是說,目錄的 block 中記錄的是這個目錄下所有一級子文件和子目錄的文件名及 inode 的對應;而文件的 block 中記錄的才是文件實際的數據。

當我們查找一個文件,比如 /root/test 時,要經過以下步驟:

  1. 首先找到根目錄的 inode(根目錄的 inode 是系統已知的,inode 號是 2),然后判斷用戶是否有權限訪問根目錄的 block。
  2. 如果有權限,則可以在根目錄的 block 中訪問到 /root 的文件名及對應的 inode 號。
  3. 通過 /root/ 目錄的 inode 號,可以查找到 /root/ 目錄的 inode 信息,接着判斷用戶是否有權限訪問 /root/ 目錄的 block。
  4. 如果有權限,則可以從 /root/ 目錄的 block 中讀取到 test 文件的文件名及對應的 inode 號。
  5. 通過 test 文件的 inode 號,就可以找到 test 文件的 inode 信息,接着判斷用戶是否有權限訪問 test 文件的 block。
  6. 如果有權限,則可以讀取 block 中的數據,這樣就完成了 /root/test 文件的讀取與訪問。


按照這個步驟,在給源文件 /root/test 建立了硬鏈接文件 /tmp/test-hard 之后,在 /root/ 目錄和 /tmp/ 目錄的 block 中就會建立 test 和 test-hard 的信息,這個信息主要就是文件名和對應的 inode 號。但是我們會發現 test 和 test-hard 的 inode 信息居然是一樣的,那么,我們無論訪問哪個文件,最終都會訪問 inode 號是 262147 的文件信息。

這就是硬鏈接的原理。硬鏈接的特點如下:

  • 不論是修改源文件(test 文件),還是修改硬鏈接文件(test-hard 文件),另一個文件中的數據都會發生改變。
  • 不論是刪除源文件,還是刪除硬鏈接文件,只要還有一個文件存在,這個文件(inode 號是 262147 的文件)都可以被訪問。
  • 硬鏈接不會建立新的 inode 信息,也不會更改 inode 的總數。
  • 硬鏈接不能跨文件系統(分區)建立,因為在不同的文件系統中,inode 號是重新計算的。
  • 硬鏈接不能鏈接目錄,因為如果給目錄建立硬鏈接,那么不僅目錄本身需要重新建立,目錄下所有的子文件,包括子目錄中的所有子文件都需要建立硬鏈接,這對當前的 Linux 來講過於復雜。


硬鏈接的限制比較多,既不能跨文件系統,也不能鏈接目錄,而且源文件和硬鏈接文件之間除 inode 號是一樣的之外,沒有其他明顯的特征。這些特征都使得硬鏈接並不常用,大家有所了解就好。

我們通過實驗來測試一下。

[root@localhost ~]# echo 1111 >>/root/test
#向源文件中寫入數據
[root@localhost ~]# cat /root/test
1111
[root@localhost ~]# cat /tmp/test-hard
1111
#源文件和硬鏈接文件都會發生改變
[root@localhost ~]# echo 2222 >> /tmp/test-hard
#向硬鏈接文件中寫入數據
[root@localhost ~]# cat /root/test
1111
2222
[root@localhost ~】# cat /tmp/test-hard
1111
2222
#源文件和硬鏈接文件也都會發生改變
[root@localhost ~]# rm -rf/root/test
#刪除源文件
[root@localhost ~]# cat /tmp/test-hard
1111 2222
#硬鏈接文件依然可常讀取

ln創建軟鏈接

軟鏈接也稱作符號鏈接,相比硬鏈接來講,軟鏈接就要常用多了。我們先建立一個軟鏈接,再來看看軟鏈接的特點。

[root@localhost ~]# touch check
#建立源文件
[root@localhost ~]# ln -s /root/check /tmp/check-soft
#建立軟鏈接文件
[root@localhost ~]# ll -id /root/check /tmp/check-soft
262154 -rw-r--r-- 1 root root 0 6月 19 11:30 /root/check
917507 lrwxrwxrwx 1 root root 11 6月 19 11:31 /tmp/ check-soft -> /root/check
#軟鏈接和源文件的 inode 號不一致,軟鏈接通過 -> 明顯地標識出源文件的位置
#在軟鏈接的權限位 lrwxrwxrwx 中,l 就代表軟鏈接文件

再強調一下,軟鏈接的源文件必須寫絕對路徑,否則建立的軟鏈接文件就會報錯,無法正常使用。

軟鏈接的標志非常明顯,首先,權限位中"l"表示這是一個軟鏈接文件;其次,在文件的后面通過 "->" 顯示出源文件的完整名字。所以軟鏈接比硬鏈接的標志要明顯得多,而且軟鏈接也不像硬鏈接的限制那樣多,比如軟鏈接可以鏈接目錄,也可以跨分區來建立軟鏈接。

軟鏈接完全可以當作 Windows 的快捷方式來對待,它的特點和快捷方式一樣,我們更推薦大家使用軟鏈接,而不是硬鏈接。

大家在學習軟鏈接的時候會有一些疑問:Windows 的快捷方式是由於源文件放置的位置過深,不容易找到,建立一個快捷方式放在桌面,方便查找,那 Linux 的軟鏈接的作用是什么呢?

筆者個人覺得,軟鏈接主要是為了照顧管理員的使用習慣。比如,有些系統的自啟動文件 /etc/rc.local 放置在 /etc 目錄中,而有些系統卻將其放置在 /etc/rc.d/rc.local 中,那么干脆對這兩個文件建立軟鏈接,不論你習慣操作哪一個文件,結果都是一樣的。

如果你比較細心,則應該已經發現軟鏈接和源文件的 inode 號是不一致的,我們也畫一張示意圖來看看軟鏈接的原理,如圖 3 所示。


軟鏈接示意圖
圖 3 軟鏈接示意圖


軟鏈接和硬鏈接在原理上最主要的不同在於:硬鏈接不會建立自己的 inode 索引和 block(數據塊),而是直接指向源文件的 inode 信息和 block,所以硬鏈接和源文件的 inode 號是一致的;而軟鏈接會真正建立自己的 inode 索引和 block,所以軟鏈接和源文件的 inode 號是不一致的,而且在軟鏈接的 block 中,寫的不是真正的數據,而僅僅是源文件的文件名及 inode 號。

我們來看看訪問軟鏈接的步驟和訪問硬鏈接的步驟有什么不同。

  1. 首先找到根目錄的 inode 索引信息,然后判斷用戶是否有權限訪問根目錄的 block。
  2. 如果有權限訪問根目錄的 block,就會在 block 中查找到 /tmp/ 目錄的 inode 號。
  3. 接着訪問 /tmp/ 目錄的 inode 信息,判斷用戶是否有權限訪問 /tmp/ 目錄的 block。
  4. 如果有權限,就會在 block 中讀取到軟鏈接文件 check-soft 的 inode 號。因為軟鏈接文件會真正建立自己的 inode 索引和 block,所以軟鏈接文件和源文件的 inode 號是不一樣的。
  5. 通過軟鏈接文件的 inode 號,找到了 check-soft 文件 inode 信息,判斷用戶是否有權限訪問 block。
  6. 如果有權限,就會發現 check-soft 文件的 block 中沒有實際數據,僅有源文件 check 的 inode 號。
  7. 接着通過源文件的 inode 號,訪問到源文件 check 的 inode 信息,判斷用戶是否有權限訪問 block。
  8. 如果有權限,就會在 check 文件的 block 中讀取到真正的數據,從而完成數據訪問。


通過這個過程,我們就可以總結出軟鏈接的特點(軟鏈接的特點和 Windows 中的快捷方式完全一致)。

  • 不論是修改源文件(check),還是修改硬鏈接文件(check-soft),另一個文件中的數據都會發生改變。
  • 刪除軟鏈接文件,源文件不受影響。而刪除原文件,軟鏈接文件將找不到實際的數據,從而顯示文件不存在。
  • 軟鏈接會新建自己的 inode 信息和 block,只是在 block 中不存儲實際文件數據,而存儲的是源文件的文件名及 inode 號。
  • 軟鏈接可以鏈接目錄。
  • 軟鏈接可以跨分區。


我們測試一下軟鏈接的特性。

[root@localhost ~]# echo 111>>/root/check
#修改源文件
[root@localhost ~]# cat /root/check
111
[root@localhost ~]# cat /tmp/check-soft
111
#不論是源文件還是軟鏈接文件,數據都發生改變
[root@localhost ~]# echo 2222 >>/tmp/check-soft
#修改軟鏈接文件
[root@localhost ~]# cat /tmp/check-soft
111
2222
[root@localhost ~]# cat /root/check
111
2222
#不論是源文件還是軟鏈接文件,數據也都會發生改變
[root@localhost ~]# rm -rf/root/check
#刪除源文件
[root@localhost ~]# cat /tmp/check-soft
cat: /tmp/check-soft:沒有那個文件或目錄
#軟鏈接無法正常使用

軟鏈接是可以鏈接目錄的,例如:

[root@localhost ~]# mkdir test
#建立源目錄
[root@localhost ~]# ln -s /root/test/ /tmp/
[root@localhost ~]# ll -d /tmp/test
lrwxrwxrwx 1 root root 11 6月 19 12:43 /tmp/test->/root/test/
#軟鏈接可以鏈接目錄

http://c.biancheng.net/view/740.html


免責聲明!

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



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