在Linux系統(tǒng)中,刪除文件可以使用rm命令,該命令底層調(diào)用了unlink系統(tǒng)調(diào)用。這里引出了一個疑問:為什么刪除文件的系統(tǒng)調(diào)用的名稱為unlink?而不是類似delete或者remove呢?
為了解釋這個疑問,先看下link系統(tǒng)調(diào)用,即創(chuàng)建硬鏈接,link系統(tǒng)調(diào)用具有兩個參數(shù),一個是舊的路徑名,一個是新的路徑名,當將一個新的路徑名“鏈接”到一個舊的路徑名時,實際上創(chuàng)建的是同一個文件的新的引用而已,而不是復制這個文件的本體,命令行程序ln可執(zhí)行此操作:
[jamza@jamza-vm files]$ ll
total 0
[jamza@jamza-vm files]$ echo hello > file1
[jamza@jamza-vm files]$ ls
file1
[jamza@jamza-vm files]$ cat file1
hello
[jamza@jamza-vm files]$ ln file1 file2
[jamza@jamza-vm files]$ ls
file1 file2
[jamza@jamza-vm files]$ cat file2
hello
在以上的操作中,link只是在要創(chuàng)建鏈接的目錄中創(chuàng)建了另一個名稱,并將其指向原來文件的相同的inode號,該文件不以任何方式復制,只是現(xiàn)在我們具有兩個人類可閱讀的文件名稱,分別為file1與file2,在底層這兩個文件名稱指向同一個文件。通過打印每個文件的inode號,我們可以確定這點:
[jamza@jamza-vm files]$ ls -il
total 2
80150690 -rw------- 2 jamza jamza 6 Jun 18 09:53 file1
80150690 -rw------- 2 jamza jamza 6 Jun 18 09:53 file2
因此,在創(chuàng)建一個文件時,實際上Linux操作系統(tǒng)完成了兩件事情:
- 構(gòu)建一個結(jié)構(gòu)(
inode),該結(jié)構(gòu)跟蹤幾乎所有關于文件的信息,包括文件的大小,文件修改時間,文件塊在磁盤上的位置等; - 將人類可讀的名稱(比如上例中的
file1與file2)鏈接到該文件,并將該鏈接放入對應目錄中。
在創(chuàng)建文件的硬鏈接后,在文件系統(tǒng)中,原有的文件名(file1)與新創(chuàng)建的文件名(file2)之間沒有區(qū)別,實際上,它們都只是指向文件底層元數(shù)據(jù)的鏈接,指向的底層元數(shù)據(jù)的inode相同(在上例中均為80150690)。
因為,為了從文件系統(tǒng)中刪除一個文件,我們將調(diào)用unlink系統(tǒng)調(diào)用,在上面的例子中,我們刪除文件名file1,但是還是可以訪問文件名file2。
[jamza@jamza-vm files]$ ls -il
total 2
80150690 -rw------- 2 jamza jamza 6 Jun 18 09:53 file1
80150690 -rw------- 2 jamza jamza 6 Jun 18 09:53 file2
[jamza@jamza-vm files]$
[jamza@jamza-vm files]$ rm file1
[jamza@jamza-vm files]$
[jamza@jamza-vm files]$ ls -il
total 1
80150690 -rw------- 1 jamza jamza 6 Jun 18 09:53 file2
[jamza@jamza-vm files]$
[jamza@jamza-vm files]$ cat file2
hello
當文件系統(tǒng)取消鏈接文件時,操作系統(tǒng)檢查inode號中的引用計數(shù),該引用計數(shù)允許文件系統(tǒng)跟蹤有多少個不同的文件名鏈接到該inode。調(diào)用unlink時,會刪除人類可閱讀的名稱與給定的inode號之間的“鏈接”,并減少引用計數(shù)。只有當引用計數(shù)達到零時,文件系統(tǒng)才會從磁盤釋放inode與相關的文件數(shù)據(jù)塊,從而真正地“刪除”該文件。
可以使用stat來查看文件的引用計數(shù)。注意以下例子中的Links字段:
[jamza@jamza-vm files]$ stat file2
File: ‘file2’
Size: 6 Blocks: 2 IO Block: 1024 regular file
Device: fc01h/64513d Inode: 80150690 Links: 1
Access: (0600/-rw-------) Uid: ( 1001/ jamza) Gid: ( 1001/ jamza)
Access: 2021-06-18 10:05:03.000000000 +0800
Modify: 2021-06-18 09:53:05.000000000 +0800
Change: 2021-06-18 10:04:54.000000000 +0800
Birth: -
[jamza@jamza-vm files]$
[jamza@jamza-vm files]$ link file2 file1
[jamza@jamza-vm files]$ link file2 file3
[jamza@jamza-vm files]$
[jamza@jamza-vm files]$ ls -il
total 3
80150690 -rw------- 3 jamza jamza 6 Jun 18 09:53 file1
80150690 -rw------- 3 jamza jamza 6 Jun 18 09:53 file2
80150690 -rw------- 3 jamza jamza 6 Jun 18 09:53 file3
[jamza@jamza-vm files]$
[jamza@jamza-vm files]$ stat file2
File: ‘file2’
Size: 6 Blocks: 2 IO Block: 1024 regular file
Device: fc01h/64513d Inode: 80150690 Links: 3
Access: (0600/-rw-------) Uid: ( 1001/ jamza) Gid: ( 1001/ jamza)
Access: 2021-06-18 10:05:03.000000000 +0800
Modify: 2021-06-18 09:53:05.000000000 +0800
Change: 2021-06-18 10:09:53.000000000 +0800
Birth: -