日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

unlink与close关系

發(fā)布時間:2025/3/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unlink与close关系 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
close和unlink。以前時候總是不太理解兩者的區(qū)別,最近看到一篇博客比較詳細地描述了二者的本質(zhì)區(qū)別,這里我引用了它的原文。 “每一個文件,都可以通過一個struct stat的結(jié)構(gòu)體來獲得文件信息,其中一個成員st_nlink代表文件的鏈接數(shù)。當通過shell的touch命令或者在程序中open一個帶有O_CREAT的不存在的文件時,文件的鏈接數(shù)為1。 通常open一個已存在的文件不會影響文件的鏈接數(shù)。open的作用只是使調(diào)用進程與文件之間建立一種訪問關(guān)系,即open之后返回fd,調(diào)用進程可以通過fd來read 、write 、 ftruncate等等一系列對文件的操作。 close()就是消除這種調(diào)用進程與文件之間的訪問關(guān)系。自然,不會影響文件的鏈接數(shù)。在調(diào)用close時,內(nèi)核會檢查打開該文件的進程數(shù),如果此數(shù)為0,進一步檢查文件的鏈接數(shù),如果這個數(shù)也為0,那么就刪除文件內(nèi)容。 link函數(shù)創(chuàng)建一個新目錄項,并且增加一個鏈接數(shù)。 unlink函數(shù)刪除目錄項,并且減少一個鏈接數(shù)。如果鏈接數(shù)達到0并且沒有任何進程打開該文件,該文件內(nèi)容才被真正刪除。如果在unlilnk之前沒有close,那么依舊可以訪問文件內(nèi)容。 綜上所訴,真正影響鏈接數(shù)的操作是link、unlink以及open的創(chuàng)建。 刪除文件內(nèi)容的真正含義是文件的鏈接數(shù)為0,而這個操作的本質(zhì)完成者是unlink。close能夠?qū)嵤﹦h除文件內(nèi)容的操作,必定是因為在close之前有一個unlink操作。”

UNIX文件系統(tǒng)包括引導(dǎo)塊、超級塊、i節(jié)點區(qū)、文件存儲區(qū)、進程對換區(qū)等幾部分。
引導(dǎo)塊占用第0號物理塊,不屬于文件系統(tǒng)管轄,如果系統(tǒng)中有多個文件系統(tǒng),只有根文件系統(tǒng)才有引導(dǎo)程序放在引導(dǎo)塊中,其余文件系統(tǒng)都不使用引導(dǎo)塊。
超級塊占用第1號物理塊,是文件系統(tǒng)的控制塊,超級塊包括:文件系統(tǒng)的大小、空閑塊數(shù)目、空閑塊索引表、空閑i節(jié)點數(shù)目、空閑i節(jié)點索引表、封鎖標記等。超級塊是文件系統(tǒng)為文件分配存儲空間、回收存儲空間的依據(jù)。
i節(jié)點區(qū)存放i節(jié)點,i節(jié)點是對文件進行控制和管理的一種數(shù)據(jù)結(jié)構(gòu)。
文件存儲區(qū)是存放文件內(nèi)容的區(qū)域,文件存儲區(qū)中各數(shù)據(jù)塊的使用情況在超級中有記錄,系統(tǒng)利用超級塊中的記錄完成對數(shù)據(jù)塊的分配和回收。
unix文件系統(tǒng)中很重要的概念之一就是i節(jié)點,下面就開始說說這個重要的概念。
每一個文件都由自己的i節(jié)點,每個i節(jié)點都有唯一的i節(jié)點號。
i節(jié)點的結(jié)構(gòu)如下(參考/usr/include/sys/ino.h)
struct dinode
{
ushort??di_mode;//文件類型與權(quán)限
short???di_nlink;
ushort di_uid;
ushort di_gid;
off_t??di_size;
char di_addr[40];
time_t di_atime;
time_t di_mtime;
time_t di_ctime;
}
從上面的結(jié)構(gòu)中可以看出:
1、i節(jié)點保存了文件的屬性和類型、存放文件內(nèi)容的物理塊地址、最近一次的存取時間、最后一次修改時間、創(chuàng)建此文件的時間。
2、i節(jié)點中沒有記錄文件名字,那么文件的名字是怎么關(guān)聯(lián)到i節(jié)點的呢?這么設(shè)計又有什么好處呢?
?????在linux系統(tǒng)中,文件的查找不是通過文件名稱來查找的。實際上是通過i節(jié)點來實現(xiàn)文件的查找定位的。我們可以形象的將i節(jié)點看作是一個指針。當文件存儲到磁盤上去的時候,文件肯定會存放到一個磁盤位置上,可以這樣想象,既然文件數(shù)據(jù)是存放在磁盤上的,如果我們知道這個文件數(shù)據(jù)的地址,當我們想讀寫文件的時候,我們是不是直接使用這個地址去找到文件就可以了呢?
?????是的,在linux下,i節(jié)點其實就是可以這么認為,把i節(jié)點看作是一個指向磁盤上該文件存儲區(qū)的地址。只不過這個地址我們一般沒辦法直接使用,而是通過文件名來間接使用的。事實上,i節(jié)點不僅包含了文件數(shù)據(jù)存儲區(qū)的地址,上面也提到過,它還包含了很多其他信息(文件的屬性和類型,存放文件內(nèi)容的物理塊地址,最近一次的存取時間,最近一次的修改時間,創(chuàng)建文件的時間)。但是i節(jié)點是不保存文件名的。文件名保存在一個目錄項中。每個目錄項中都包含了文件名和i節(jié)點。回到正題,i節(jié)點中沒有記錄文件愛你名字,那么文件按名是怎么關(guān)聯(lián)到i節(jié)點的呢。這里就關(guān)系到了硬鏈接與符號鏈接的區(qū)別。
如下圖:

???????對于硬鏈接來說,如果刪掉源文件helloA.c,那么磁盤上數(shù)據(jù)文件按是不會被刪除的。因為i節(jié)點上記錄了該文件的硬鏈接數(shù)。只有硬鏈接數(shù)為0的時候,刪除文件名的時候,該數(shù)據(jù)在磁盤上才會刪除。
???????所謂的符號鏈接,其實是指文件索引的索引。當源文件helloB.c刪除之后,其實磁盤數(shù)據(jù)文件還在,helloC.c也無法使用。符號鏈接包含了一個文件名的路徑,如果這個文件名被刪除,這個符號鏈接自然就不能正常工作了。
3、di_mode這個是怎么保存文件類型+用戶權(quán)限的呢?
比如:
drwxr-xr-x?????????7?????????root????????????sys??????????????512??????dec??15???2012???var
?-rw-r--r---?????????1?????????root????????????sys??????????????4003?????Ju1 4 23 : 37??????1
紅色字體部分說明是文件類型標記和文件權(quán)限,這個字符串跟ushort di_mode怎么關(guān)聯(lián)的?
ushort di_mode是16位2進制數(shù),保存的就是文件類型及用戶權(quán)限信息,具體結(jié)構(gòu)如下:
4??????????????????8????????????????????12????????????????????16
第1-4位:文件類型
第5位:suid位
第6位:sgid位
第7位:sticky位
第8-10位:文件屬主權(quán)限位
第11-13位:文件屬組權(quán)限位
第14-16位:其他用戶權(quán)限位
1)文件類型分類:
d--目錄文件、f--普通文件、b--塊設(shè)備文件、c--字符設(shè)備文件、l--鏈接文件
2)文件類型位算法
從系統(tǒng)的頭文件/usr/include/sys/stat.h中可以知道:
a、#define???S_IFMT???0170000 -- 文件類型掩碼宏,0170000以0開頭,表示這是一個8進制數(shù),轉(zhuǎn)換成2進制,正好是 1 111 000 000 000 000 ,高4位全置1;
b、#define???S_IFREG 0100000 -- 普通文件類型掩碼,0100000,轉(zhuǎn)換成2進制,1 000 000 000 000 000,最高位置1;
c、#define S_ISREG(m)???(((m) & S_IFMT) == S_IFREG) --???判斷文件是否普通文件的宏函數(shù)
舉例說明:m值即為我們?nèi)〉絬short di_mode,假設(shè)其2進制值為 0 011 000 000 000 000,對應(yīng)的8進制為 060000???。S_ISREG(0060000) 即 (((0060000) & 0170000 ) == 0100000) ,該值返回False,則代表該文件不是普通文件。


說明:stat結(jié)構(gòu)中的大多數(shù)信息都取自i節(jié)點。只有兩項數(shù)據(jù)存放在目錄項中:文件名和i節(jié)點編號。i節(jié)點編號的數(shù)據(jù)類型是ino_t。
注意:每個文件系統(tǒng)各自對它們的i節(jié)點進行編號,因此目錄項中的i節(jié)點編號數(shù)指向同一文件系統(tǒng)中相應(yīng)的i節(jié)點,不能使一個目錄項指向另一個文件系統(tǒng)的i節(jié)點。
討論linux中l(wèi)ink,unlink,close,fclose函數(shù)對st_nlink的影響
?????linux中每一個文件,都可以通過一個struct stat的結(jié)構(gòu)體來獲得文件信息,其中一個成員st_nlink代表文件的鏈接數(shù)。
???????當通過shell的touch命令或者在程序中open一個帶有O_CREAT的不存在的文件時,文件的鏈接數(shù)為1。
???????通常open一個已存在的文件不會影響文件的鏈接數(shù)。open的作用只是使調(diào)用進程與文件之間建立一種訪問關(guān)系,即open之后返回fd,調(diào)用進程可以通過fd來read 、write 、 ftruncate等等一系列對文件的操作。
???????close()就是消除這種調(diào)用進程與文件之間的訪問關(guān)系。自然,不會影響文件的鏈接數(shù)。在調(diào)用close時,內(nèi)核會檢查打開該文件的進程數(shù),如果此數(shù)為0,進一步檢查文件的鏈接數(shù),如果這個數(shù)也為0,那么就刪除文件內(nèi)容。
???????link函數(shù)創(chuàng)建一個新目錄項,并且增加一個鏈接數(shù)。
???????unlink函數(shù)刪除目錄項,并且減少一個鏈接數(shù)。如果鏈接數(shù)達到0并且沒有任何進程打開該文件,該文件內(nèi)容才被真正刪除。如果在unlilnk之前沒有close,那么依舊可以訪問文件內(nèi)容。
???????綜上所訴,真正影響鏈接數(shù)的操作是link、unlink以及open的創(chuàng)建。
???????刪除文件內(nèi)容的真正含義是文件的鏈接數(shù)為0,而這個操作的本質(zhì)完成者是unlink。close能夠?qū)嵤﹦h除文件內(nèi)容的操作,必定是因為在close之前有一個unlink操作。
???????舉個例子簡單說明:通過shell???touch test.txt
??1 #include <stdio.h>
??2 #include <unistd.h>
??3 #include <sys/stat.h>
??4 #include <sys/types.h>
??5 #include <fcntl.h>
??6
??7 int main(int argc,char *argv[])
??8 {
??9?????struct stat buf;
?10?????stat("test.txt",&buf);
?11?????printf("1.link=%d\n",buf.st_nlink);
?12
?13 int fd;
?14 fd = open("test.txt",O_RDONLY);
?15 stat("test.txt",&buf);
?16 printf("2.link=%d\n",buf.st_nlink);
?17
?18?????close(fd);
?19?????stat("test.txt",&buf);
?20?????printf("3.link=%d\n",buf.st_nlink);
?21 link("test.txt","test2.txt");
?22 stat("test.txt",&buf);
?23 printf("4.link=%d\n",buf.st_nlink);
?24?????unlink("test2.txt");
?25?????stat("test.txt",&buf);
?26?????printf("5.link=%d\n",buf.st_nlink);
?27 fd = open("test.txt",O_RDONLY);
?28 stat("test.txt",&buf);
?29 printf("6.link=%d\n",buf.st_nlink);
?30?????unlink("test.txt");
?31?????fstat(fd,&buf);
?32?????printf("7.link=%d\n",buf.st_nlink);
?33
?34?????return 0;
?35
?36 }
順次執(zhí)行以上8個步驟,結(jié)果如下:
1.link=1
2.link=1????//open不影響鏈接數(shù)
3.link=1????//close不影響鏈接數(shù)
4.link=2????//link之后鏈接數(shù)加1
5.link=1????//unlink后鏈接數(shù)減1
6.link=1????//重新打開??鏈接數(shù)不變
7.link=0????//unlink之后再減1,此處我們改用fstat函數(shù)而非stat,因為unlilnk已經(jīng)刪除文件名,所以不可以通過???文件名訪問,但是fd仍然是打開著的,文件內(nèi)容還沒有被真正刪除,依舊可以使用fd獲得文件信息。
執(zhí)行步驟8,文件內(nèi)容被刪除....
注意:在第步驟6中,文件test.txt此時已經(jīng)打開并沒有將其關(guān)閉,而步驟七中直接將其釋放,此時,文件的內(nèi)容沒有真正的被刪除。進程任然可以繼續(xù)讀文件中的內(nèi)容。直到關(guān)閉該文件或進程結(jié)束自動關(guān)閉后,內(nèi)核首先會先檢查打開文件的進程數(shù),如果為0,然后內(nèi)核檢查其鏈接數(shù),由于在第七步中已經(jīng)釋放了最后一個,所以其鏈接數(shù)為0,那么就刪除該文件的內(nèi)容。
下圖是抄之a(chǎn)pue的精典例子:


????unlink的這種性質(zhì)經(jīng)常被程序用來確保即使是在該程序崩潰時,它所創(chuàng)建的臨時文件也不會被遺留下來。進程用open或creat創(chuàng)建一個文件,然后立即調(diào)用unlink。因為該文件仍舊是打開的,所以不會將其內(nèi)容刪除。只有當進程關(guān)閉該文件或終止時(這種情況下,內(nèi)核會關(guān)閉該進程打開的全部文件),該文件的內(nèi)容才會被刪除。
????unlink刪除該符號鏈接,而不是刪除由該鏈接所引用的文件。給出符號鏈接名的情況下,沒有一個函數(shù)能刪除由該鏈接所引用的文件。

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的unlink与close关系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。