最近在重溫大學的經典課程:Linux。每天工作之余的時間,坐在家里的陽台上,簡簡單單的紀錄一些基本的知識點,對我來說,既溫暖又難得。
有朋友問我關於cp和ln建立符號鏈接(軟鏈接)和硬鏈接的一些問題,在這里做個記錄。
cp 命令
基本用法:
cp source destination
該命令將source復制至一個新文件,叫destination。注意,這種復制,是真實將源文件內容拷貝了一份,存在了物理存儲空間。
我們使用命令ls -il來顯示文件的長列表,會發現destination與source有不同的索引節點號(索引節點是內核分配給文件系統中每個對象的唯一標識數字)。
root@iZ28eyzqmtxZ:~# ls jdk log.txt root@iZ28eyzqmtxZ:~# cp log.txt log2.txt root@iZ28eyzqmtxZ:~# ls -il total 4 786442 drwxr-xr-x 2 root root 4096 Jun 6 22:33 jdk 787736 -rw-r--r-- 1 root root 0 Jul 2 11:36 log2.txt 787737 -rw-r--r-- 1 root root 0 Jun 14 17:29 log.txt root@iZ28eyzqmtxZ:~#
cp命令有很多參數,可以進行諸如遞歸復制整個目錄中的所有內容等。相關參數可以參看Linux編程大全。
這里要解釋的是-l和-s兩個參數。
-l:創建文件鏈接(硬鏈接)而非復制文件
-s:創建一個符號鏈接(軟鏈接)而非復制文件
雖然沒有看過Linux的源碼,但是可以推斷出這邊用到了c中的兩個特性:指針,指針的指針。
我們知道操作系統在進行存儲管理的時候,會為文件存儲的物理空間的起點標識一個確定的“地址”,而我們所見的文件名,其實在存儲空間中,存儲的是真實源文件的“地址”,這個地址指向了源文件的真實存儲空間。
如上圖,存儲空間A和存儲空間B可能是相鄰的存儲空間,也可能不是,但它們一定是兩個存儲空間存了相同的內容。
再看硬鏈接的圖:
也就是說我們如果執行的是 cp -l log.txt log2.txt,實際上並沒有創建一份新的源文件,只是對存儲空間A新加了一個指向它的指針。
root@iZ28eyzqmtxZ:~# ls jdk log2.txt log.txt root@iZ28eyzqmtxZ:~# ls -il total 4 786442 drwxr-xr-x 2 root root 4096 Jun 6 22:33 jdk 787736 -rw-r--r-- 1 root root 0 Jul 2 11:36 log2.txt 787737 -rw-r--r-- 1 root root 0 Jun 14 17:29 log.txt root@iZ28eyzqmtxZ:~# cp -l log.txt log3.txt root@iZ28eyzqmtxZ:~# ls -il total 4 786442 drwxr-xr-x 2 root root 4096 Jun 6 22:33 jdk 787736 -rw-r--r-- 1 root root 0 Jul 2 11:36 log2.txt 787737 -rw-r--r-- 2 root root 0 Jun 14 17:29 log3.txt 787737 -rw-r--r-- 2 root root 0 Jun 14 17:29 log.txt root@iZ28eyzqmtxZ:~#
可見,log.txt和log3.txt公用同一個索引節點號:787737,而且它們倆的硬鏈接總數都變成了2。即存儲空間A有兩個指向它的指針。
這樣一來,無論我們是查找log.txt還是log3.txt,都會先找到它們代表的0xA300的存儲空間,接着便能找到並操作源文件。
我們在這邊可以先解釋一個已經可以解釋的問題:既然log.txt和log3.txt指向同一個源文件,為什么刪除log3.txt之后,仍然可以訪問log.txt?
在Linux編程大全講解硬鏈接的內容中有這樣一句話:硬鏈接會一直維持源文件對應的索引節點號來保留數據,直到你刪除了最后一個硬鏈接它的文件。
也就是說,對於存儲空間A來說,你刪除了log3.txt之后,只是斷掉了一個指向它的指針而已,並沒有執行刪除源文件的操作。
自此,我們講完了硬鏈接,其實就是一個指針的概念,硬鏈接的指針,是指向真實文件的指針,而接下來要講的軟鏈接,也是一個指針,只不過這個指針指向的是一個地址,該地址也是一個指針,指向真實文件。所以軟鏈接(符號鏈接),即指針的指針。
上面我們舉例說到log.txt代表的是0xA300,這個“0xA300”也需要存在存儲空間中,也就是說它也具有一個地址,我們假設為0xA000。那么執行軟鏈接操作:
cp -s log.txt log4.txt之后真實的存儲情況長這樣。
訪問log4.txt時先找到了它代表的0xA000,找到了0xA000存儲空間中存儲的內容:0xA300,發現它丫的還是一個指針,接着找,找到了存儲真實文件的存儲空間A。
這里我們可以解釋另一個現象,就是為什么刪除了log.txt之后,無法訪問log4.txt?
這個你自己想吧,中間斷掉了,它訪問0xA000,嗯,發現里面啥都沒有!接着就會告訴你它已經不復存在了,然而你使用ls命令的時候,仍然能看到log4.txt這個文件名,只是無法查看它的內容了。
忠告:
不要覺得軟鏈接和硬鏈接如此牛逼,就一頓亂用,人家是有使用場合的,比如硬鏈接,是你在同種媒體介質上不想為相同的內容耗費兩份存儲空間的時候使用的,而軟鏈接是你想在不同掛載點上使用該文件的時候使用的(即不能在不同掛載點下的文件間創建硬鏈接)。
如果你一個勁的使用軟鏈接,就會各種斷,各種崩。
ln命令
ln命令可以代替cp命令,默認情況下,ln命令會創建硬鏈接,要加上參數 -s以創建軟鏈接。