? ? 在Linux下面的鏈接文件有兩種,
- 一種是類似Windows的快捷方式功能的文件,可以讓你快速地鏈接到目標文件(或目錄);
- 另一種則是通過文件系統的inode 鏈接來產生新文件名,而不是產生新文件,這種稱為硬鏈接(hard link),這兩種玩意兒是完全不一樣的東西,現在就分別來談談。
1.硬鏈接(Hard Link,硬式鏈接或實際鏈接)
我們知道幾件重要的信息,包括:
- 每個文件都會占用一個inode,文件內容由inode的記錄來指向;
- 想要讀取該文件,必須要經過目錄記錄的文件名來指向到正確的inode號碼才能讀取。
也就是說,其實文件名只與它所處的目錄有關,但是文件內容則與它自己的inode有關。
那么想一想,有沒有可能有多個文件名對應到同一個inode號碼?
有的,那就是硬鏈接的由來,所以簡單地說:硬鏈接只是在某個目錄下新增一條文件名鏈接到某inode號碼的關聯記錄而已。
由于linux下的文件是通過索引節點(Inode)來識別文件,硬鏈接可以認為是一個指針,指向文件索引節點的指針,系統并不為它重新分配inode。每添加一個一個硬鏈接,文件的鏈接數就加1。
我們看個例子?
#根目錄下創建文件夾hardlink,并且在hardlink內創建文件aa.txt
#查看其鏈接數為1,注意,此處鏈接數就是硬鏈接的次數
#創建硬鏈接
#往aa.txt文件中寫入一些內容
#發現aa.link中也同樣可以看到#刪除aa.txt,aa.link依然可以正常查看內容,鏈接數 -1,inode不變
我們回過頭來看這個例子
你有沒有發現兩個文件名都鏈接到1048579這個inode號碼,所以你看看是不是所以您看看,是否文件的權限與屬性完全一樣?
因為這兩個文件名其實是一模一樣的文件,而且你也會發現第二個字段由原本的1變成2,那個字段稱為鏈接,這個字段的意義為:有多少個文件名鏈接到這個inode 號碼。如果將讀取到正確數據的方式畫成示意圖,就類似下圖:
上圖的意思是,你可以通過User1或User2或User3的目錄的inode指定的區塊找到兩個不同的文件名,而不管使用哪個文件名均可以指到那個 inode去讀取到最終數據。那這樣有什么好處?
- 最大的好處就是安全,如同上圖中,如果你將任何一個文件名刪除,其實inode與區塊都還是存在的。此時你可以通過另一個文件名來讀取到正確的文件數據。
- 此外,不論你使用哪個文件名來編輯,最終的結果都會寫入到相同的inode與區塊中,因此均能進行數據的修改。
一般來說,使用硬鏈接設置鏈接文件時,磁盤的空間與inode的數目都不會改變。
由圖中可以知道,硬鏈接只是在某個目錄下的區塊多寫入一個關聯數據而已,既不會增加inode 也不會消耗區塊數量。
我們接著上面那個例子來講
那這時候,就有個疑問了,如果鏈接數只剩下一個,再次刪除,會進行什么樣的操作呢?
?實際上,
- 如果我們這時候再刪除aa.link這個文件,系統只會刪除掉inode table中aa.link指向的inode信息,和hardlink 目錄項中aa.link的相關信息。
- 然后會將aa.link inode指針(也就是硬鏈接)所指向的數據塊設置為空閑的狀態,告訴系統這些數據塊可以被再次使用。
- 而里面的內容卻不會被刪除,直到新的數據覆蓋為止!
????????這也就說明了,實際上 linux中被刪除的文件數據是可以被找回的,只要相應的數據塊沒有被再次覆蓋使用。
????????如果觀察的再細致一些,我們會發現,為什么hardlink這個文件夾在創建后就會有兩個鏈接數呢?
通過上述查看,我們可以看出,當進入hardlink目錄下后,默認會有個 .的隱藏目錄,而該目錄也就是當前目錄的意思,即hardlink目錄。所以才會有兩個鏈接數。
硬鏈接的制作中其實還是可能會改變系統的區塊,那就是當你新增這條數據卻剛好將目錄的區塊填滿時,就可能會新加一個區塊來記錄文件名關聯性,而導致磁盤空間的變化。不過,一般硬鏈接所用掉的關聯數據量很小,所以通常不會改變inode與磁盤空間的大小
1.1.硬鏈接的缺點
1、無法跨分區,跨設備創建硬鏈接
[root@localhost hardlink]# ln aa.link /boot/
ln: failed to create hard link ‘/boot/aa.link’ => ‘aa.link’: Invalid cross-device link
因為每個分區都有自己獨立的inode體系,
假設A分區的文件在B分區做了一個硬鏈接,此時訪問B分區的此鏈接,按照我們想的是需要它訪問A分區的inode,進行數據查詢,但是它只會根據B分區的inode,在B數據塊中查找數據。
就相當于兩套獨立的數據庫,你不可能拿著A數據庫的某個主鍵去B數據庫搜索數據,是一樣的道理。
2、無法創建文件夾/目錄的硬鏈接
至于為何設置為無法創建文件夾,這里還是用反推來驗證。
假設可以創建文件夾的硬鏈接:ln? /hardlink? /test/dir.link。那么有個問題,首當其沖。?
hardlink目錄下的 . 是當前目錄的意思,此處代表hardlink,那dir.link中的 ‘.’是代表test目錄呢?還是 hardlink目錄呢?
其次,假設存在目錄 /A/B.link 和 /B/A.link。如果B.link是B目錄的硬鏈接,A.link是A目錄的硬鏈接。那A.link既然是/A的鏈接,那它里面肯定有B.link。同理B.link里面肯定有A.link。這樣依次循環 /A/B.link/A.link/B.link/A.link/…。就造成了死循環的現象。這也就是為什么不允許創建文件夾硬鏈接的原因了。
由于硬鏈接局限性比較多,所以工作中使用的不多。
2.符號鏈接(Symbolic Link,亦即是快捷方式)
相對于硬鏈接,符號鏈接可就好理解多了。
符號鏈接相當于我們 Windows 中的快捷方式,即如果你軟鏈接一個目錄,只是一個目錄的快捷方式到指定位置,操作系統找這個快捷方式會直接找到真實目錄下的文件。
基本上,符號鏈接就是建立一個獨立的文件,而這個文件會讓數據的讀取指向它鏈接的那個文件的文件名。
由于只是利用文件來做為指向的操作,所以,當源文件被刪除之后,符號鏈接的文件會【打不開了】,會一直說【無法打開某文件】,實際上就是找不到原始文件名而已。
創建軟鏈接
由上圖的結果我們可以知道兩個文件指向不同的inode號碼,當然就是兩個獨立的文件存在。
而且鏈接文件的重要內容就是它會寫上目標文件的文件名,你可以發現上表中鏈接文件的大小為6B。因為箭頭(-->)右邊的文件名【aa.txt】總共有6個字母,每個字母占用1個字節,所以文件大小就是12B了。
但是事實真的是這樣子嗎?它真的存是是文件名嗎?
事實上,軟連接記錄的是鏈接文件箭頭后面的路徑字符串大小
不信的話我們來驗證一下
這里我們寫入一些內容到aa.txt中?
再次查看,原文件大小發生了改變,而鏈接文件大小依舊沒變化。
這其實就是軟鏈接的特性之一,因為軟鏈接的inode指向的數據塊保存的是 原文件的路徑,如果沒有路徑,是由文件名,默認會在軟鏈接所在路徑查找
?
再次舉例論證
ls.link大小正好是 /usr/bin/ls的路徑字符串大小?
軟鏈接的使用,如果觀察Centos7,會發現,既有使用相對路徑創建的軟鏈接,也有使用絕對路徑創建的軟鏈接。
而使用相對路徑創建軟鏈接,則有如下注意點:
上圖中,我們使用 ln -s …/aa.txt /tmp/aa.link在/tmp下創建了軟鏈接,卻發現,竟然提示報錯!找不到aa.txt。
????????因為/tmp/aa.link在指向…/aa.txt 的過程中。它會以自己的路徑為初始點去尋找aa.txt。即 /tmp/aa.link -> …/aa.txt,在系統看來,它會理解成。以aa.link所在路徑為起點,回到上一級目錄,去尋找aa.txt。很顯然沒有找到,所以報錯。
????????創建的軟連接,指向的文件,默認會以軟鏈接的路徑為主,去尋找指向的文件,所以創建時,請以軟鏈接的路徑作為起點路徑 去寫原文件的相對路徑
????????那既然相對路徑創建這么麻煩,為什么還要使用這種方式呢?
因為使用相對路徑的話,遷移只要相對遷移,不會影響鏈接的使用,更加靈活。而絕對路徑的軟鏈接,則必須要求路徑的正確性。
而由于軟鏈接 inode指向的數據塊只保存 原文件的地址字符串,所以可以跨分區、跨設備創建,并且文件夾也可以創建。
當然如果原文件被刪除了,鏈接則也會失效,無法向硬鏈接那樣擁有獨立性。
基本上,符號鏈接的用途比較廣,所以您要特別留意符號鏈接的用法,未來一定還會常常用到。?
3、軟鏈接與硬鏈接的區別
- 1、本質:
硬鏈接:同一個inode,只是多個名字。
軟鏈接:是不同的文件,inode不同
- 2、跨分區
硬鏈接無法跨分區、跨設備建立,軟鏈接可以
- 3、目錄
硬鏈接無法創建目錄硬鏈接,軟鏈接可以
- 4、相互關系
硬鏈接沒有主次之分,相互獨立
軟鏈接依賴于原文件,原文件被刪除,軟鏈接即不可用
- 5、鏈接數
硬鏈接會刪除增加會影響鏈接數,軟鏈接不會,因為inode不一樣。
- 6、相對路徑
硬鏈接創建時,原始文件路徑是相對于當前路徑。
軟鏈接創建時,原始文件路徑是 相對于軟鏈接的路徑
- 7、文件類型
硬鏈接的類型與原始文件類型一致,軟鏈接則會顯示 symbolic link
- 8、創建方式
硬鏈接創建:ln [原文件] [硬鏈接]
軟鏈接創建:ln -s [原文件] [軟鏈接]
4.關于目錄的鏈接數量
或許您已經發現了,那就是,當我們以硬鏈接進行文件的鏈接時,可以發現,在ls-l所顯示的第二字段會增加一才對,那么請教,如果建立目錄時,它默認的鏈接數量會是多少?
讓我們來想一想,一個空目錄里面至少會存在些什么?
呵呵,就是存在.與..這兩個目錄。
那么,當我們建立一個新目錄名稱為/tmp/testing時,基本上會有三個東西,那就是:
- /tmp/testing
- /tmp/testing/.
- /tmp/testing/..
而其中/tmp/testing與/tmp/testing/.其實是一樣的。都代表該目錄,而/tmp/testing/.則代表/tmp 這個目錄。所以說,當我們建立一個新的目錄時,【新的目錄的鏈接數為2,而上層目錄的鏈接數則會增加1】
不信的話,我們來做個測試看看:
看,原本的所謂上層目錄/tmp的鏈接數量由10增加為11,至于新目錄/tmp/testing則為2。這
樣可以理解目錄鏈接數量的意義了嗎?
?