如果使用 hard link 鏈接到目錄時(shí), 鏈接的數(shù)據(jù)需要連同被鏈接目錄底下的所有數(shù)據(jù)都創(chuàng)建鏈接,舉例來(lái)說(shuō),如果你要將 /etc 使用實(shí)體鏈接創(chuàng)建一個(gè) /etc_hd 的目錄時(shí),那么在 /etc_hd 底下的所有檔名同時(shí)都與 /etc 底下的檔名要?jiǎng)?chuàng)建 hard link 的,而不是僅連結(jié)到 /etc_hd 與 /etc 而已。 并且,未來(lái)如果需要在 /etc_hd 底下創(chuàng)建新文件時(shí),連帶的, /etc 底下的數(shù)據(jù)又得要?jiǎng)?chuàng)建一次 hard link ,因此造成環(huán)境相當(dāng)大的復(fù)雜度。 所以啰,目前 hard link 對(duì)于目錄暫時(shí)還是不支持的啊!
說(shuō)法二:
先假設(shè)可以:即現(xiàn)在你有目錄/d1/d2和目錄/d3/d4硬鏈接,都指向同一結(jié)點(diǎn)(inode),現(xiàn)在分別在兩個(gè)目錄(d2和d4)下進(jìn)行cd ..
結(jié)果會(huì)是怎樣呢?
也許你認(rèn)為,它們有相同的結(jié)點(diǎn),故他們應(yīng)該指向同一父目錄,這應(yīng)該是d1,但對(duì)于d4,其父目錄又是d3,于是問(wèn)題就產(chǎn)生了,
這取決于d2和d4是哪個(gè)先創(chuàng)建的,這將會(huì)給目錄結(jié)構(gòu)造成混亂……
說(shuō)法三:
直觀(guān)理解是,如果允許硬鏈接指向目錄,假設(shè)目錄.../d1/...與.../d2/...互為硬鏈接,那么在d1下必然包含目錄項(xiàng)“..”,試問(wèn)這個(gè)“..”應(yīng)該指向d1還是d2?
深層剖析如下:
linux系統(tǒng)中的硬連接有兩個(gè)限制:不能跨越文件系統(tǒng)和不允許普通用戶(hù)對(duì)目錄作硬連接。至于第一個(gè)限制,很好理解,而第二個(gè)就不那么好理解了。我們對(duì)任何一個(gè)目錄用ls -l 命令都可以看到其連接數(shù)至少是2,這也說(shuō)明了系統(tǒng)中是存在硬連接的,而且命令ln -d 也可以讓超級(jí)用戶(hù)對(duì)目錄作硬連接,這些都說(shuō)明了系統(tǒng)限制對(duì)目錄進(jìn)行硬連接只是一個(gè)硬性規(guī)定,并不是邏輯上不允許或技術(shù)上的不可行。那么操作系統(tǒng)為什么要進(jìn)行限制呢?答案可能有兩個(gè)。
先來(lái)說(shuō)第一個(gè),如果引入了對(duì)目錄的硬連接就有可能在目錄中引入循環(huán),那么在目錄遍歷的時(shí)候系統(tǒng)就會(huì)陷入無(wú)限循環(huán)當(dāng)中。也許您會(huì)說(shuō),符號(hào)連接不也可以引入循環(huán)嗎,那么為什么不限制目錄的符號(hào)連接呢?原因就在于在linux系統(tǒng)中,每個(gè)文件(目錄也是文件)都對(duì)應(yīng)著一個(gè)inode結(jié)構(gòu),其中inode數(shù)據(jù)結(jié)構(gòu)中包含了文件類(lèi)型(目錄,普通文件,符號(hào)連接文件等等)的信息,也就是說(shuō)操作系統(tǒng)在遍歷目錄時(shí)可以判斷出符號(hào)連接,既然可以判斷出符號(hào)連接當(dāng)然就可以采取一些措施來(lái)防范進(jìn)入過(guò)大的循環(huán)了,系統(tǒng)在連續(xù)遇到8個(gè)符號(hào)連接后就停止遍歷,這就是為什么對(duì)目錄符號(hào)連接不會(huì)進(jìn)入死循環(huán)的原因了。但是對(duì)于硬連接,由于操作系統(tǒng)中采用的數(shù)據(jù)結(jié)構(gòu)和算法限制,目前是不能防范這種死循環(huán)的。
在說(shuō)明第二個(gè)原因之前,我們先來(lái)看看文件的dentry結(jié)構(gòu)在系統(tǒng)空間中長(zhǎng)什么樣子和它們是怎么存放在系統(tǒng)空間的。dentry結(jié)構(gòu)主要包含了文件名,文件的inode 號(hào),指向父目錄dentry結(jié)構(gòu)的指針和其他一些與本次討論無(wú)關(guān)的指針,這里關(guān)鍵是那個(gè)指向父目錄的指針;系統(tǒng)中所有的dentry結(jié)構(gòu)都是按雜湊值存放在雜湊表中的,這里的雜湊算法很重要,它是取文件名和文件的父目錄dentry結(jié)構(gòu)的地址一起雜湊運(yùn)算出雜湊值的。現(xiàn)在我們假設(shè)有兩個(gè)目錄 /a和/b,其中/b是我們通過(guò)ln -d命令建立起來(lái)的對(duì)/a的硬連接。這個(gè)時(shí)候內(nèi)核空間中就會(huì)存在一個(gè)/a的dentry結(jié)構(gòu)和一個(gè)/b的dentry結(jié)構(gòu),由上面的知識(shí)可知,/a和/b 目錄下面的每一個(gè)文件或目錄都各自有對(duì)應(yīng)的dentry結(jié)構(gòu)(因?yàn)殡m然/a目錄下面的文件名沒(méi)有改變,但是因?yàn)閐entry結(jié)構(gòu)有指向父目錄dentry 的指針和計(jì)算雜湊值時(shí)考慮了父目錄dentry結(jié)構(gòu)的地址,這個(gè)時(shí)候dentry結(jié)構(gòu)就分身乏術(shù)了),而且這種繼承還會(huì)影響到所有子目錄下面的文件,這樣下來(lái)就會(huì)浪費(fèi)很多系統(tǒng)空間了,特別是如果被硬連接的目錄中存在大量文件和子目錄的時(shí)候就更加明顯了。這也許是第二個(gè)原因。