從symbol link和hard link 到 unlink函數的一點記錄

    之前一直對Linux的文件類型中的 “l” 類型的瞭解不是很深入,最近經過“聖經”指點,略知一二,在此先記錄一下,以便以後查閱,之後會對文件和目錄、文件I/O這部分再擴充。

    首先需明確,Unix在查閱文件類型時,首先調用的是stat函數,格式如下:

   int  stat(const char *restrict pathname , struct stat *restrictbuf)

   成功則返回0(出錯返回-1),得到7種文件類型如下:

1.普通文件 (-)

2.目錄文件 (d)

3.塊特殊文件 (b)

4.字符特殊文件 (c)

5.FIFO (用於進程間通信,也叫命名管道 )

6.套接字 (socket)

7.符號鏈接 (l)

     平時我們新手接觸最多的就是普通文件以及目錄文件,同時也會接觸到標誌爲“l”的文件,在此先介紹硬鏈接和軟鏈接。

     硬鏈接實際上是一個指針,指向源文件的inode,系統並不爲它重新分配inode。任何一個文件可以有多個目錄項指向其inode,硬鏈接不會產生新的inode,硬連接不管有多少個,都指向的是同一個inode節點,只是新建一個hard link會把結點連接數增加,只要結點的連接數不是0,文件就一直存在,不管你刪除的是源文件還是連接的文件。只要有一個存在,文件就存在(其實就是引用計數的概念)。當你修改源文件或者連接文件任何一個的時候,其他的文件都會做同步的修改。(引自http://blog.csdn.net/yasaken/article/details/7292186)。此時,我們可以試一下,找一個佔用磁盤大一些的測試文件,,然後ln建立一個hard link,發現此時該文件的類型就是普通文件,如下圖,而且佔用同樣大的磁盤空間,當我隨便去試圖修改一個文件時,由於這些硬鏈接文件指向同一個inode,因此所有文件都做出同步的修改,該文件的鏈接計數爲2,當我們unlink隨便一個文件時,鏈接計數減一,則只刪去unlink路徑下的那個硬鏈接文件,實際的文件並沒有刪除。   

               

      通過以上的實驗,我個人認爲是否可以將硬鏈接看成是cp一個文件,因爲硬鏈接文件同樣佔用磁盤空間,但是這個cp文件與源文件指向同一個inode,因此相當於創建了一個會和源文件的數據塊時刻保持同步的文件。(注意:hard link只能指向自己文件系統的inode,無法跨越文件系統。如果要想實現支持創建指向一個目錄的硬鏈接,那麼也僅限於root,這其實是不被推薦的,容易在文件系統中形成循環。POSIX.1常量LINK_MAX指定了一個文件鏈接數的最大值爲8.)。link 函數以及linkat函數調用方式如下:

   int  link (const char *existingpath,  const char *newpath);

   int  linkat (int efd, const char *exsitingpath, int nfd, const char *newpath, int flag);

   軟鏈接最直觀的解釋:相當於Windows系統的快捷方式,是一個獨立文件(擁有獨立的inode,與源文件inode無關),該文件的內容是源文件的路徑指針,通過該鏈接可以訪問到源文件。所以刪除軟鏈接文件對源文件無影響,但是刪除源文件,軟鏈接文件就會找不到要指向的文件(可以類比Windows上快捷方式,你點擊快捷方式可以訪問某個文件,但是刪除快捷方式,對源文件無任何影響)。命令可以用:ln  -s   源文件的絕對路徑   軟鏈接文件的絕對路徑

   在此注意,指定路徑時,一定要指定絕對路徑,否則會出現找不到鏈接的源文件的情況。如下圖:軟鏈接已經建立,但是無法通過軟鏈接打開源文件。如果不使用絕對路徑的話,就要在腳本中調用linkat函數,通過設置文件描述符efd和nfd的標誌爲AT_FDCWD(強制通過相對於調用進程的當前目錄計算pathname),與相對路徑來計算文件的路徑(目前我還沒有涉及到)。

  由於軟鏈接文件與源文件的inode無關,所以是可以跨越文件系統的。同時,軟鏈接的操作權限是777的,但是如果你要對此進行編輯,需要的權限是源文件的權限,而硬鏈接的操作權限與源文件保持一致。

   下面說一下由此引發的對unlink的一點記錄。

    爲了刪除一個現有的目錄項,可以調用unlink函數,如下:

   int  unlink (const char *pathname);

   int  unlinkat (int fd ,const char *pathname, int flag);

   當我們要想刪除一個文件時,必須要具備兩個條件:

   1.鏈接計數達到0,該文件纔可以被刪除。

   2.只要有進程打開了文件,其內容也不能刪除。

如下面一段代碼:

int
main(void)
{
	if (open("tempfile", O_RDWR|O_CREAT) < 0)
		err_sys("open error");
	if (unlink("tempfile") < 0)
		err_sys("unlink error");
	printf("file unlinked\n");
	sleep(15);
	printf("done\n");
	exit(0);
}

    當我們執行unlink後,雖然計數爲0,實際上並沒有將文件刪除,而是要經過15秒後的exit(0)使進程調用關閉後,才真正的刪除了該文件,正是那句printf讓我糾結了大半天。敲打  具體的執行exit(0)做的東西以後再擴充。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章