獲獎+答案公布:Linux符號鏈接和硬鏈接的小測試
假設目錄「~」下面不存在a, b, c這樣的文件,在該目錄下面執行如下命令:
題目步驟
$ echo hello > a
$ ln a b
$ ln -s a c
$ rm a
$ echo world > a
請問接下來執行
「cat b」
輸出什麼?執行"cat c」
輸出什麼?解釋為什麼!詳細論述其中關於inode等的變化。雖然很多童鞋的答案都是正確的,但是獲獎名單只能有三人。眾多童鞋的回答參見做題免費送書:關於Linux符號鏈接和硬鏈接的小測試的留言。
我們根據答案回復的先後順序,答案的精細度、準確度和完整度,選取了3個優勝者。獲獎名單與答案如下:
wsl
「cat b」 的輸出是 hello, 「cat c」 是world
首先解釋為什麼」cat b「 輸出是hello, b 文件是a 文件的硬鏈接,而硬鏈接實際
是同一個文件,因為他們的inode number 是相同的。比如筆者的測試環境:
$ ls -i a
473972 a
$ln a b
$ ls -i b
473972 b
既然是同一個文件,a 和b 的文件內容相同,雖然第四步刪除了文件a 但是inode 引用數只是減了1,
並不為0,inode 並沒有刪除。
下面解釋為什麼 「cat c」的輸出
首先創建了一個名為c 的軟連接,c 本質上是一個新文件(inode number不同於a)c 的文件內容是a的路徑
$ ls -i c
480580 c
$cat c
hello
此時cat c,默認讀一個link 文件, 內核FOLLOW_LINK, 也就是會讀c 指向的文件a的內容。
第四步刪除了a, 此時c 文件本身不受影響,c文件內容也不受影響,但是如果此時cat c
則會輸出:
cat: c: No such file or directory
因為FOLLOW link目標文件,目標文件已經不存在了。最後一步重新創建了一個a 文件,
cat c 會輸出新創建文件的內容。本質上c 文件始終沒有發生變化,他的內容是就是a 的path.
紅燒的威化餅
cat b顯示的是hello
cat c顯示的是world
原因
echo hello > a 新建a(設inode number為10),內容為hello
ln a b,創建硬鏈接b,和a共用一個inode,不同的dentry
ln -s a c 創建軟連接c指向a,不與a共用inode
rm a 刪除a文件,由於inode10有兩個reference,只把它的reference減1,不刪除數據,但是由於a沒了,
所以c這個軟連接失效。
echo world > a 新建一個新文件,假設inode number為20,內容為world,此時a和b是兩個不同的文件,c是軟鏈接指向a
桂雄~
$ echo hello > a
這裡會創建a文件,此時a文件內容是hello
$ ln a b
這裡創建了一個硬鏈接b,b與a指向同一個inode
$ ln -s a c
這裡創建了一個軟鏈接c,c的文件的實際內容就是a文件的路徑
$ rm a
刪除a文件對b沒有影響,不過這個inode的引i_nlink就會減一,但是c文件的由於保存的是a文件路徑名指向,因此a文件被刪了後,c文件的指向就不存在了,此時cat c會報文件不存在的錯誤。
$ echo world > a
此時echo world又創建一個文件,文件名是a,但是此時的inode已經是重新申請到的,a與b已經不是硬鏈接關係了,但是c文件的軟鏈接文件a又存在了,因此此時c文件cat的話就不會報錯了
cat b的話會輸出hello
因為這是在最初a創建的時候寫進去的,然後b跟他共享了inode,因此文件內容還是hello
cat c的話輸出world
這裡c是新建的a的軟鏈接,這個a文件已經不是原來的a文件,c文件軟鏈接的也不是原來的a文件,而是最後輸入world的時候創建的新的a文件。而c文件軟鏈接到了a文件,因此cat到的就是新的a文件內容。
恭喜這三位童鞋!!祝大家中秋快樂。
查看"Linux閱碼場"精華技術文章請移步:
Linux閱碼場原創精華文章匯總
掃描二維碼關注
"Linux閱碼場"
推薦閱讀:
