每一個檔案,都可以通過一個struct stat的結構體來獲得檔案資訊,其中一個成員st_nlink代表檔案的連結數。
struct stat {unsigned longst_dev;/* Device. */unsigned longst_ino;/* File serial number. */unsigned intst_mode;/* File mode. */unsigned intst_nlink;/* Link count. */unsigned intst_uid;/* User ID of the file's owner. */unsigned intst_gid;/* Group ID of the file's group. */unsigned longst_rdev;/* Device number, if device. */unsigned long__pad1;longst_size;/* Size of file, in bytes. */intst_blksize;/* Optimal block size for I/O. */int__pad2;longst_blocks;/* Number 512-byte blocks allocated. */longst_atime;/* Time of last access. */unsigned longst_atime_nsec;longst_mtime;/* Time of last modification. */unsigned longst_mtime_nsec;longst_ctime;/* Time of last status change. */unsigned longst_ctime_nsec;unsigned int__unused4;unsigned int__unused5;};
當通過shell的touch命令或者在程式中open一個帶有O_CREAT的不存在的檔案時,檔案的連結數為1。
通常open一個已存在的檔案不會影響檔案的連結數。open的作用只是使調用進程與檔案之間建立一種訪問關係,即open之後返回fd,調用進程可以通過fd來read 、write 、 ftruncate等等一系列對檔案的操作。
close()就是消除這種調用進程與檔案之間的訪問關係。自然,不會影響檔案的連結數。在調用close時,核心會檢查開啟該檔案的進程數,如果此數為0,進一步檢查檔案的連結數,如果這個數也為0,那麼就刪除檔案內容。
link函數建立一個新目錄項,並且增加一個連結數。
unlink函數刪除目錄項,並且減少一個連結數。如果連結數達到0並且沒有任何進程開啟該檔案,該檔案內容才被真正刪除。如果在unlilnk之前沒有close,那麼依舊可以訪問檔案內容。
綜上所訴,真正影響連結數的操作是link、unlink以及open的建立。
刪除檔案內容的真正含義是檔案的連結數為0,而這個操作的本質完成者是unlink。close能夠實施刪除檔案內容的操作,必定是因為在close之前有一個unlink操作。
舉個例子簡單說明:通過shell touch test.txt
1、stat("test.txt",&buf);
printf("1.link=%d\n",buf.st_nlink);//未開啟檔案之前測試連結數
2、fd=open("test.txt",O_RDONLY);//開啟已存在檔案test.txt
stat("test.txt",&buf);
printf("2.link=%d\n",buf.st_nlink);//測試連結數
3、close(fd);//關閉檔案test.txt
stat("test.txt",&buf);
printf("3.link=%d\n",buf.st_nlink);//測試連結數
4、link("test.txt","test2.txt");//建立永久連結test2.txt
stat("test.txt",&buf);
printf("4.link=%d\n",buf.st_nlink);//測試連結數
5、unlink("test2.txt");//刪除test2.txt
stat("test.txt",&buf);
printf("5.link=%d\n",buf.st_nlink);//測試連結數
6、重複步驟2 //重新開啟test.txt
7、unlink("test.txt");//刪除test.txt
fstat(fd,&buf);
printf("7.link=%d\n",buf.st_nlink);//測試連結數
8、close(fd);//此步驟可以不顯示寫出,因為進程結束時,開啟的檔案自動被關閉。
順次執行以上8個步驟,結果如下:
1.link=1
2.link=1 //open不影響連結數
3.link=1 //close不影響連結數
4.link=2 //link之後連結數加1
5.link=1 //unlink後連結數減1
2.link=1 //重新開啟 連結數不變
7.link=0 //unlink之後再減1,此處我們改用fstat函數而非stat,因為unlilnk已經刪除檔案名稱,所以不可以通過 檔案名稱訪問,但是fd仍然是開啟著的,檔案內容還沒有被真正刪除,依舊可以使用fd獲得檔案資訊。
執行步驟8,檔案內容被刪除。。。。