佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > Linux unlink函數(shù)和刪除文件的操作方法

Linux unlink函數(shù)和刪除文件的操作方法

熱門(mén)標(biāo)簽:百度競(jìng)價(jià)點(diǎn)擊價(jià)格的計(jì)算公式 檢查注冊(cè)表項(xiàng) 美圖手機(jī) 阿里云 硅谷的囚徒呼叫中心 智能手機(jī) 網(wǎng)站建設(shè) 使用U盤(pán)裝系統(tǒng)

1. unlink函數(shù)

  對(duì)于硬鏈接來(lái)說(shuō),unlink 用來(lái)刪除目錄項(xiàng),并把 inode 引用計(jì)數(shù)減 1,這兩步也是一個(gè)原子過(guò)程。直到 inode 引用計(jì)數(shù)為 0,才會(huì)真正刪除文件。

  對(duì)于軟鏈接來(lái)說(shuō),unlink 直接刪除軟鏈接,而不影響軟鏈接指向的文件。

函數(shù)原型:

int unlink(const char *pathname);  

參數(shù)說(shuō)明:

  pathname:指定要移除的鏈接文件

返回值說(shuō)明:

  成功返回0;失敗則返回-1,同時(shí)設(shè)置errno為相應(yīng)值

2. 實(shí)驗(yàn)代碼—myunlink

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]){ 
 //為一個(gè)已經(jīng)存在的文件創(chuàng)建目錄項(xiàng)(硬鏈接)
 if(link(argv[1], argv[2]) == -1){
 perror("link error");
 exit(1);
 }
 //刪除之前的文件目錄項(xiàng)
 if(unlink(argv[1]) == -1){
 perror("unlink error");
 exit(1);
 }
 return 0;
}

  當(dāng)我們執(zhí)行./myunlink hellotest命令完后,會(huì)刪除 hellotest,同時(shí) inode 引用計(jì)數(shù)減 1。

3. 刪除文件

  不用說(shuō),相信大家都用過(guò)rm -rf命令吧。

  現(xiàn)在我們?cè)賮?lái)思考一下,以前我們通過(guò)rm命令刪除文件時(shí)你有沒(méi)有質(zhì)疑過(guò),文件真的被刪除掉了嗎?

  如果真的刪除的了話,那么操作系統(tǒng)又是怎么把文件刪除掉的?

  操作系統(tǒng)在設(shè)計(jì)的時(shí)候是通過(guò)把文件的inode索引號(hào)與磁盤(pán)中的block塊建立了關(guān)聯(lián),這樣我們通過(guò)文件找到block塊的位置,也就看到了文件的數(shù)據(jù)了。

  在刪除文件時(shí),是由系統(tǒng)的2個(gè)變量來(lái)控制的一個(gè)是i_link,表示文件的硬鏈接數(shù)量,另一個(gè)是i_count,表示文件的引用計(jì)數(shù),文件刪除的必需條件就是i_link = 0和i_count = 0。

  在磁盤(pán)中的文件只要把i_link = 0(硬鏈接數(shù)干掉)就可以把文件刪除了,如果這個(gè)文件在程序中被打開(kāi),我們還需要把運(yùn)行的程序干掉 i_count = 0,這樣才能達(dá)到刪除文件的目的。

4. linux下刪除文件的大概過(guò)程

  linux下文件刪除過(guò)程大概如圖: 

 

圖1-linux下文件刪除的大概過(guò)程

  當(dāng)前磁盤(pán)中的/test/file目錄下有一個(gè)test文件(i_link = 1),還有一個(gè)硬鏈接文件hard_link指向test文件(i_link = 1),且./test進(jìn)程又打開(kāi)了test文件(i_count = 1),如果要?jiǎng)h除test.txt文件,必須把./test進(jìn)程干掉(i_count = 0),然后刪除hard_link硬鏈接文件和/test/file目錄下的test.txt文件(也就是讓i_link = 0)。

  也就是說(shuō)linux下是通過(guò)link的數(shù)量來(lái)控制文件刪除的,當(dāng)一個(gè)文件的link = 0時(shí),這個(gè)文件才會(huì)被刪除。一般一個(gè)文件有2個(gè)link計(jì)數(shù)器,一個(gè)是i_link和i_count。

  i_count是當(dāng)前進(jìn)程打開(kāi)文件的引用計(jì)數(shù),i_link是文件鏈接的數(shù)量,可以把i_count理解為內(nèi)存中文件的計(jì)數(shù)器,而i_link是磁盤(pán)中的計(jì)數(shù)器。對(duì)于rm命令來(lái)說(shuō)實(shí)際就是設(shè)置磁盤(pán)中文件的i_link計(jì)數(shù)為0。如果一個(gè)文件被進(jìn)程所使用,而用戶又執(zhí)行了rm命令把文件刪除掉了,此時(shí)程序還能正常執(zhí)行,依舊能從文件中讀取正確的數(shù)據(jù),這是因?yàn)閞m命令只是把i_link設(shè)置為 0(是將文件到inode的關(guān)聯(lián)斷開(kāi),并沒(méi)有刪除掉inode與磁盤(pán)中的block數(shù)據(jù)塊,此時(shí)停止進(jìn)程,被刪除的數(shù)據(jù)可以找回來(lái),如果進(jìn)程正在寫(xiě)入數(shù)據(jù),那么磁盤(pán)的block塊的數(shù)據(jù)會(huì)被進(jìn)程寫(xiě)入的數(shù)據(jù)覆蓋掉,原先的數(shù)據(jù)就恢復(fù)不了了)。

  而進(jìn)程仍然在引用該文件i_count = 1,執(zhí)行rm命令系統(tǒng)并不會(huì)真正的刪除該文件,如果要?jiǎng)h除該文件必須讓進(jìn)程解除對(duì)該文件的引用計(jì)數(shù),也就是把進(jìn)程干掉,這樣文件才會(huì)被真正的刪除掉。

  即便如此,文件真的被刪除了嗎?前面我們說(shuō)過(guò)文件的數(shù)據(jù)是存儲(chǔ)在磁盤(pán)上block塊中,當(dāng)我們要查找文件當(dāng)中的數(shù)據(jù)時(shí)并不是直接找到磁盤(pán)上的block塊,因?yàn)榇疟P(pán)上的block塊實(shí)在是太多了,你怎么就知道你的數(shù)據(jù)存儲(chǔ)在哪個(gè)block塊中?

  假設(shè)你一不小心把非常重要的數(shù)據(jù)刪除掉了,這將意味著你的數(shù)據(jù)就永遠(yuǎn)也找不回來(lái)了,從而造成無(wú)法挽回的損失了,由此可見(jiàn)數(shù)據(jù)的重要性,因此操作系統(tǒng)不會(huì)輕易把數(shù)據(jù)從磁盤(pán)中真正的刪除掉。

  看到這里,相信你已經(jīng)明白了,實(shí)際上你所謂的右鍵刪除操作只是把文件的inode索引號(hào)與磁盤(pán)中的block的關(guān)聯(lián)斷開(kāi)了而已,但文件的數(shù)據(jù)并沒(méi)有真正的被刪除掉。如果你想真的刪除數(shù)據(jù)的話,要么把磁盤(pán)格式化,要么把原先的數(shù)據(jù)刪除掉,然后寫(xiě)入新的數(shù)據(jù)覆蓋掉,當(dāng)然,你也可以選擇格式化和數(shù)據(jù)覆蓋雙重保險(xiǎn),這個(gè)時(shí)候你的數(shù)據(jù)想要恢復(fù)基本上是非常困難的,即便可以頂多只能恢復(fù)一部分?jǐn)?shù)據(jù)了吧。

  如果你真的一不小心刪除了很重要的數(shù)據(jù)的話,這個(gè)時(shí)候趕緊恢復(fù)數(shù)據(jù),其他的任何多余的操作盡量不要做,這樣在數(shù)據(jù)恢復(fù)過(guò)程中才能盡量減少數(shù)據(jù)丟失。

5. myunlink2.c程序

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 /*
 unlink函數(shù)是刪除一個(gè)dentry
 */
int main(void){
 int fd;
 char *p = "test of unlink\n";
 char *p2 = "after write something.\n";
 //當(dāng)進(jìn)程打開(kāi)temp.txt文件時(shí),引用計(jì)數(shù)會(huì)+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文件寫(xiě)入第一個(gè)字符串,通過(guò)返回值判斷寫(xiě)操作是否成功
 ret = write(fd, p, strlen(p));
 if (ret == -1) {
 perror("-----write error");
 }
 printf("hi! I'm printf\n");
 //向temp.txt文件寫(xiě)入第二個(gè)字符串,通過(guò)返回值判斷寫(xiě)操作是否成功
 ret = write(fd, p2, strlen(p2));
 if (ret == -1) {
 perror("-----write error");
 }
 printf("Enter anykey continue\n");
getchar();
 //當(dāng)close關(guān)閉fd的時(shí)候,進(jìn)程對(duì)文件的引用計(jì)數(shù)就會(huì)-1,斷開(kāi)進(jìn)程與文件的關(guān)聯(lián)關(guān)系
 close(fd);
 return 0;
}

程序運(yùn)行結(jié)果:

  程序的運(yùn)行結(jié)果和我們所預(yù)料的一樣,當(dāng)程序運(yùn)行的時(shí)候,調(diào)用open函數(shù)創(chuàng)建并打開(kāi)了temp.txt文件,此時(shí)進(jìn)程對(duì)temp文件的引用計(jì)數(shù)i_count會(huì)加1,同時(shí)temp文件本身也會(huì)有一個(gè)i_link鏈接計(jì)數(shù)也會(huì)加1。

  當(dāng)調(diào)用了unlink函數(shù)刪除temp文件時(shí),只是把i_link鏈接計(jì)數(shù)減1,而進(jìn)程的i_count計(jì)數(shù)還是1,并沒(méi)有斷開(kāi)與temp文件的關(guān)聯(lián)關(guān)系,因此進(jìn)程可以調(diào)用write函數(shù)往temp文件里面寫(xiě)數(shù)據(jù),自然也就能成功了。當(dāng)程序運(yùn)行結(jié)束后,調(diào)用close關(guān)閉對(duì)temp文件的引用,此時(shí)temp文件就會(huì)被操作系統(tǒng)刪除掉。

6. 總結(jié)

  在不了解文件系統(tǒng)原理的情況下,通常我們會(huì)認(rèn)為數(shù)據(jù)已經(jīng)刪除掉,其實(shí)不然,磁盤(pán)上的文件數(shù)據(jù)還在,只是把dentry目錄和磁盤(pán)上的數(shù)據(jù)的聯(lián)系斷開(kāi),我們找不到數(shù)據(jù)肯定會(huì)認(rèn)為刪掉了,但是只要我們想辦法讓數(shù)據(jù)和dentry目錄之間重新建立連接,就可以讓刪除的數(shù)據(jù)恢復(fù)。

  因此我們刪除文件,從某種意義上說(shuō),只是讓文件具備了被釋放的條件,至于什么時(shí)候釋放這取決于操作系統(tǒng)。

  對(duì)于unlink函數(shù)來(lái)說(shuō),清除文件時(shí),如果文件的硬鏈接數(shù)到0了,沒(méi)有dentry對(duì)應(yīng),但該文件仍不會(huì)馬上被釋放。要等到所有打開(kāi)該文件的進(jìn)程關(guān)閉該文件,系統(tǒng)才會(huì)挑時(shí)間將該文件釋放掉。

7. 不要隨便使用rm命令

  相信看到這里,你應(yīng)該知道了,數(shù)據(jù)對(duì)于計(jì)算機(jī)的重要性了,因?yàn)橐坏┠承┲陵P(guān)重要的數(shù)據(jù)刪除了,那就真的永遠(yuǎn)沒(méi)了,這也是操作系統(tǒng)為什么不直接將數(shù)據(jù)從磁盤(pán)中刪除的原因。但也不要因?yàn)檫@樣,你就可以肆無(wú)忌憚的使用rm命令了,因?yàn)橛袝r(shí)候數(shù)據(jù)刪除了,并不能百分百的恢復(fù)回來(lái)。

總結(jié)

以上所述是小編給大家介紹的Linux unlink函數(shù)和刪除文件的操作方法,希望對(duì)大家有所幫助,也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

標(biāo)簽:懷化 賀州 湖北 煙臺(tái) 山南 湘潭 黃山 通遼

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Linux unlink函數(shù)和刪除文件的操作方法》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    莱州市| 柯坪县| 许昌县| 新巴尔虎左旗| 渑池县| 团风县| 漠河县| 西乌| 大渡口区| 宜黄县| 崇明县| 长宁县| 天祝| 白山市| 永城市| 九寨沟县| 瑞昌市| 长垣县| 万山特区| 渭南市| 大荔县| 新竹市| 秦安县| 图们市| 静海县| 延寿县| 洛南县| 岐山县| 汨罗市| 佳木斯市| 景谷| 合山市| 安溪县| 富平县| 慈利县| 桃园县| 乐安县| 西安市| 阳城县| 孟州市| 黄冈市|