Linux 中的檔案分為 Hard Link 和 Symbolic Link 兩種。Hard Link 檔案又被稱為硬連結檔案、實體連結檔案,Symbolic Link 檔案則常被稱為符號連結、軟連結檔案。
ln 命令用來在檔案之間建立連結。在介紹 ln 命令前,讓我們先來搞清楚究竟什麼是硬連結,什麼又是軟連結。
Hard Link(硬連結)
我們知道,在 Linux 系統中,每個檔案對應一個 inode,檔案的內容在儲存在 inode 指向的 data block 中。要讀取該檔案的內容,需要透過檔案所在的目錄中記錄的檔名找到檔案的 inode 號,然後透過 inode 找到儲存檔案內容的 data block(參考《Linux 檔案與目錄》)。
也就是說,檔名儲存在目錄中,inode 號執行檔案儲存的內容,檔名和 inode 之間有一個對應關係。那麼多個檔名可不可以同時指向同一個 inode 呢?答案是可以的,這就是硬連結!從本質上來說,硬連結只是在目錄下新新增了一個檔名,這個檔名與一個已有檔案的 inode 相關聯。讓我們也透過 /etc/crontab 檔案來進行觀察:
$ ll -i /etc/crontab 131213 -rw-r--r-- 1 root root 722 Nov 16 2017 /etc/crontab
使用 ln 命令在當前目錄下建立一個 /etc/crontab 檔案的硬連結,然後觀察其檔案屬性:
$ sudo ln /etc/crontab . $ ll -i /etc/crontab crontab 131213 -rw-r--r-- 2 root root 722 Nov 16 2017 crontab 131213 -rw-r--r-- 2 root root 722 Nov 16 2017 /etc/crontab
這兩個檔名關聯的 inode 號完全相同,都是 131213,所以它們指向的是同一個檔案。同時請注意檔案屬性中的第三個欄位,由 1 變成了 2。這個欄位被稱為 "連結數",它說明有多少個檔名連結到同一個檔案的 inode。
另外需要注意的一點是上面所有輸出中的第二個欄位中的第一位,它們都是 "-",它說明這個檔案的型別為普通檔案,連結型別為硬連結。
我們可以透過下圖來理解硬連結在檔案系統中的實現方式:
硬連結的特點
- 幾乎不額外佔用空間
- 只要還有一個檔名引用著檔案,檔案就不會被真正刪除
由於硬連結只是在目錄中新增了一條包含檔名和 對應 inode 的記錄,所以它幾乎不會消耗額外的磁碟容量。
另外在刪除硬連結所關聯的檔案時,其實只是刪除了一條目錄中的記錄,真正的檔案並不受影響。只有在刪除最後一個硬連結時才會真正刪除檔案的內容資料。
硬連結的侷限性
- 不能跨檔案系統建立硬連結
- 不能連結目錄
由於這兩個限制,實際使用中硬連結並沒有軟連結使用的廣泛,下面我們看看究竟什麼是軟連結。
Symbolic Link(軟連結)
軟連結的實現方式與硬連結有本質上的不同。建立軟連結時會建立一個新的檔案(分配一個 inode 和對應的 data block),新檔案的 data block 中儲存了目標檔案的路徑。
還拿 /etc/crontab 檔案舉例子,這次建立一個軟連結並檢視其檔案屬性:
$ sudo ln -s /etc/crontab crontab2
第一列,兩個檔名對應的 inode 不同,說明這是兩個檔案。
第二列顯示的檔案許可權也不一樣,這一點和硬連結完全不同。注意檔案型別被標記為 "l",說明這是一個軟連結檔案。
第三列很有意思,注意 /etc/crontab 檔案的連結數量,還是 2,這和建立軟連結檔案 crontab2 前是一樣的。也就是說建立軟連結並不增加原檔案的連結數。
第六列是檔案大大小,注意新建的軟連結檔案大小為 12 Bytes,也就是字串 "/etc/crontab" 的長度。
最後一列會友好的顯示出軟連結檔案指向的原始檔。
我們可以透過下圖來理解軟連結在檔案系統中的實現方式:
從上圖我們可以看出,軟連結檔案 crontab2 是一個實實在在的檔案,有自己的 inode 和 data block。但是它的 data block 中儲存的是目標檔案的地址:/etc/crontab。 像 open() 這樣的 API 能夠識別出軟連結,並根據 data block 中的目標檔案徑把操作重定向到目標檔案上。
可以連結目錄是軟連結的一大優勢,建立目錄連結的方式和普通檔案一樣:
$ ln -s /bin testbin
此時進入 testbin 目錄和進入 /bin 目錄是一樣的。
更厲害的是,還可以跨檔案系統建立軟連結!
刪除原始檔
對於軟連結來說,刪除源連結後,連結檔案就會無法找到指向的原始檔了。看下面的演示:
$ echo "hello world" > hello.txt $ ln -s hello.txt hello2 $ cat hello2 hello world $ rm hello.txt $ cat hello2 cat: hello2: No such file or directory
刪除原檔案後,操作連結檔案時的提示是:"No such file or directory"。
檔案的連結數
從上文中的示例我們可以看到,當建立硬連結檔案時,檔案的連結數會增加 1,而建立軟連結時檔案的連結數卻不發生變化。
下面讓我們看一個目錄檔案的連結數,先建立一個空目錄:
$ mkdir /home/nick/testdir $ ll /home/nick | grep testdir drwxr-xr-x 2 nick nick 4096 Jul 10 08:58 testdir/
新建的空目錄有兩個硬連結,分別是:
/home/nick/testdir
/home/nick/testdir/.
而 /home/nick/testdir 目錄下還有一個指向其父目錄的硬連結:/home/nick/testdir/..
也就是說當我們建立一個目錄時,其父目錄的硬連結數會增加 1。
ln 命令
ln 命令用來在檔案之間建立連結,其的常用方式為:
ln source target
ln -s source target
它們分別用來建立硬連結檔案和軟連結檔案。還有一個比較常用的選項是 f,它會強制刪除已經存在的目標檔案。
參考:
ln man page
鳥哥的私房菜
徹底理解“軟連結”和“硬連結”
The difference between hard and soft links