您好,登錄后才能下訂單哦!
小編給大家分享一下Linux中unlink函數和刪除文件的操作方法,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
Linux是一種免費使用和自由傳播的類UNIX操作系統,是一個基于POSIX的多用戶、多任務、支持多線程和多CPU的操作系統,使用Linux能運行主要的Unix工具軟件、應用程序和網絡協議。
1. unlink函數
??對于硬鏈接來說,unlink 用來刪除目錄項,并把 inode 引用計數減 1,這兩步也是一個原子過程。直到 inode 引用計數為 0,才會真正刪除文件。
??對于軟鏈接來說,unlink 直接刪除軟鏈接,而不影響軟鏈接指向的文件。
函數原型:
int unlink(const char *pathname);
參數說明:
??pathname:指定要移除的鏈接文件
返回值說明:
??成功返回0;失敗則返回-1,同時設置errno為相應值
2. 實驗代碼—myunlink
#include <unistd.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char *argv[]){ //為一個已經存在的文件創建目錄項(硬鏈接) if(link(argv[1], argv[2]) == -1){ perror("link error"); exit(1); } //刪除之前的文件目錄項 if(unlink(argv[1]) == -1){ perror("unlink error"); exit(1); } return 0; }
??當我們執行./myunlink hellotest命令完后,會刪除 hellotest,同時 inode 引用計數減 1。
3. 刪除文件
??不用說,相信大家都用過rm -rf命令吧。
??現在我們再來思考一下,以前我們通過rm命令刪除文件時你有沒有質疑過,文件真的被刪除掉了嗎?
??如果真的刪除的了話,那么操作系統又是怎么把文件刪除掉的?
??操作系統在設計的時候是通過把文件的inode索引號與磁盤中的block塊建立了關聯,這樣我們通過文件找到block塊的位置,也就看到了文件的數據了。
??在刪除文件時,是由系統的2個變量來控制的一個是i_link,表示文件的硬鏈接數量,另一個是i_count,表示文件的引用計數,文件刪除的必需條件就是i_link = 0和i_count = 0。
??在磁盤中的文件只要把i_link = 0(硬鏈接數干掉)就可以把文件刪除了,如果這個文件在程序中被打開,我們還需要把運行的程序干掉 i_count = 0,這樣才能達到刪除文件的目的。
4. linux下刪除文件的大概過程
??linux下文件刪除過程大概如圖:
圖1-linux下文件刪除的大概過程
??當前磁盤中的/test/file目錄下有一個test文件(i_link = 1),還有一個硬鏈接文件hard_link指向test文件(i_link = 1),且./test進程又打開了test文件(i_count = 1),如果要刪除test.txt文件,必須把./test進程干掉(i_count = 0),然后刪除hard_link硬鏈接文件和/test/file目錄下的test.txt文件(也就是讓i_link = 0)。
??也就是說linux下是通過link的數量來控制文件刪除的,當一個文件的link = 0時,這個文件才會被刪除。一般一個文件有2個link計數器,一個是i_link和i_count。
??i_count是當前進程打開文件的引用計數,i_link是文件鏈接的數量,可以把i_count理解為內存中文件的計數器,而i_link是磁盤中的計數器。對于rm命令來說實際就是設置磁盤中文件的i_link計數為0。如果一個文件被進程所使用,而用戶又執行了rm命令把文件刪除掉了,此時程序還能正常執行,依舊能從文件中讀取正確的數據,這是因為rm命令只是把i_link設置為 0(是將文件到inode的關聯斷開,并沒有刪除掉inode與磁盤中的block數據塊,此時停止進程,被刪除的數據可以找回來,如果進程正在寫入數據,那么磁盤的block塊的數據會被進程寫入的數據覆蓋掉,原先的數據就恢復不了了)。
??而進程仍然在引用該文件i_count = 1,執行rm命令系統并不會真正的刪除該文件,如果要刪除該文件必須讓進程解除對該文件的引用計數,也就是把進程干掉,這樣文件才會被真正的刪除掉。
??即便如此,文件真的被刪除了嗎?前面我們說過文件的數據是存儲在磁盤上block塊中,當我們要查找文件當中的數據時并不是直接找到磁盤上的block塊,因為磁盤上的block塊實在是太多了,你怎么就知道你的數據存儲在哪個block塊中?
??假設你一不小心把非常重要的數據刪除掉了,這將意味著你的數據就永遠也找不回來了,從而造成無法挽回的損失了,由此可見數據的重要性,因此操作系統不會輕易把數據從磁盤中真正的刪除掉。
??看到這里,相信你已經明白了,實際上你所謂的右鍵刪除操作只是把文件的inode索引號與磁盤中的block的關聯斷開了而已,但文件的數據并沒有真正的被刪除掉。如果你想真的刪除數據的話,要么把磁盤格式化,要么把原先的數據刪除掉,然后寫入新的數據覆蓋掉,當然,你也可以選擇格式化和數據覆蓋雙重保險,這個時候你的數據想要恢復基本上是非常困難的,即便可以頂多只能恢復一部分數據了吧。
??如果你真的一不小心刪除了很重要的數據的話,這個時候趕緊恢復數據,其他的任何多余的操作盡量不要做,這樣在數據恢復過程中才能盡量減少數據丟失。
5. myunlink2.c程序
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <stdio.h> /* unlink函數是刪除一個dentry */ int main(void){ int fd; char *p = "test of unlink\n"; char *p2 = "after write something.\n"; //當進程打開temp.txt文件時,引用計數會+1 fd = open("temp.txt", O_RDWR|O_CREAT|O_TRUNC, 0644); if(fd < 0){ perror("open temp error"); exit(1); } //具備了被釋放的條件 int ret = unlink("temp.txt"); if(ret < 0){ perror("unlink error"); exit(1); } //向temp.txt文件寫入第一個字符串,通過返回值判斷寫操作是否成功 ret = write(fd, p, strlen(p)); if (ret == -1) { perror("-----write error"); } printf("hi! I'm printf\n"); //向temp.txt文件寫入第二個字符串,通過返回值判斷寫操作是否成功 ret = write(fd, p2, strlen(p2)); if (ret == -1) { perror("-----write error"); } printf("Enter anykey continue\n"); getchar(); //當close關閉fd的時候,進程對文件的引用計數就會-1,斷開進程與文件的關聯關系 close(fd); return 0; }
程序運行結果:
??程序的運行結果和我們所預料的一樣,當程序運行的時候,調用open函數創建并打開了temp.txt文件,此時進程對temp文件的引用計數i_count會加1,同時temp文件本身也會有一個i_link鏈接計數也會加1。
??當調用了unlink函數刪除temp文件時,只是把i_link鏈接計數減1,而進程的i_count計數還是1,并沒有斷開與temp文件的關聯關系,因此進程可以調用write函數往temp文件里面寫數據,自然也就能成功了。當程序運行結束后,調用close關閉對temp文件的引用,此時temp文件就會被操作系統刪除掉。
6. 總結
??在不了解文件系統原理的情況下,通常我們會認為數據已經刪除掉,其實不然,磁盤上的文件數據還在,只是把dentry目錄和磁盤上的數據的聯系斷開,我們找不到數據肯定會認為刪掉了,但是只要我們想辦法讓數據和dentry目錄之間重新建立連接,就可以讓刪除的數據恢復。
??因此我們刪除文件,從某種意義上說,只是讓文件具備了被釋放的條件,至于什么時候釋放這取決于操作系統。
??對于unlink函數來說,清除文件時,如果文件的硬鏈接數到0了,沒有dentry對應,但該文件仍不會馬上被釋放。要等到所有打開該文件的進程關閉該文件,系統才會挑時間將該文件釋放掉。
7. 不要隨便使用rm命令
??相信看到這里,你應該知道了,數據對于計算機的重要性了,因為一旦某些至關重要的數據刪除了,那就真的永遠沒了,這也是操作系統為什么不直接將數據從磁盤中刪除的原因。但也不要因為這樣,你就可以肆無忌憚的使用rm命令了,因為有時候數據刪除了,并不能百分百的恢復回來。
看完了這篇文章,相信你對“Linux中unlink函數和刪除文件的操作方法”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。