1. 程式人生 > >檔案描述符

檔案描述符

在C程式中,檔案由檔案指標或者檔案描述符表示。ISO C的標準I/0庫函式(fopen, fclose, fread, fwrite, fscanf, fprintf等)使用檔案指標,UNIX的I/O函式(open, close, read, write, ioctl)使用檔案描述符。下面重點來說下,檔案描述符是如何工作的。

檔案描述符相當於一個邏輯控制代碼,而open,close等函式則是將檔案或者物理裝置與控制代碼相關聯。控制代碼是一個整數,可以理解為程序特定的檔案描述符表的索引。先介紹下面三個概念,後面講下open、close等操作以後,檔案和檔案描述符產生什麼關係,以及fork後文件描述符的繼承等問題。

檔案描述符表:使用者區的一部分,除非通過使用檔案描述符的函式,否則程式無法對其進行訪問。對程序中每個開啟的檔案,檔案描述符表都包含一個條目。

系統檔案表:為系統中所有的程序共享。對每個活動的open, 它都包含一個條目。每個系統檔案表的條目都包含檔案偏移量、訪問模式(讀、寫、or 讀-寫)以及指向它的檔案描述符表的條目計數。

記憶體索引節點表: 對系統中的每個活動的檔案(被某個程序打開了),記憶體中索引節點表都包含一個條目。幾個系統檔案表條目可能對應於同一個記憶體索引節點表(不同程序開啟同一個檔案)。

1、舉例: 執行myfd = open( "/home/lucy/my.dat", O_RDONLY); 以後,上述3個表的關係原理圖如下:

                        

                                                                               圖1

系統檔案表包含一個偏移量,給出了檔案當前的位置。若2個程序同時開啟一個檔案(如上圖A,B)做讀操作,每個程序都有自己相對於檔案的偏移量,而且讀入整個檔案是獨立於另一個程序的;如果2個程序開啟同一個檔案做寫操作,寫操作是相互獨立的,每個程序都可以重寫另一個程序寫入的內容。

如果上面程序在open以後又執行了close()函式,作業系統會刪除檔案描述符表的第四個條目,和系統檔案表的對應條目(若指向它的描述符表唯一),並對記憶體索引節點表條目中的計數減1,如果自減以後變為0,說明沒有其他程序連結此檔案,將索引節點表條目也刪除,而這裡程序B也在open這個檔案,所以索引節點表條目保留。

2、檔案描述符的繼承

通過fork()建立子程序時,子程序繼承父程序環境和上下文的大部分內容的拷貝,其中就包括檔案描述符表。

(1)對於父程序在fork()之前開啟的檔案來說,子程序都會繼承,與父程序共享相同的檔案偏移量。如下圖所示(0-1-2 表示 標準輸入-輸出-錯誤):

                     

                                                                  圖2 fork()之前開啟my.dat

 

系統檔案表位於系統空間中,不會被fork()複製,但是系統檔案表中的條目會儲存指向它的檔案描述符表的計數,fork()時需要對這個計數進行維護,以體現子程序對應的新的檔案描述符表也指向它。程式關閉檔案時,也是將系統檔案表條目內部的計數減一,當計數值減為0時,才將其刪除。

 

(2)相反,如果父程序先程序fork,再開啟my.dat,這時父子程序關於my.dat 的檔案描述符表指向不同的系統檔案表條目,也不再共享檔案偏移量(fork以後2個程序分別open,在系統檔案表中建立2個條目);但是關於標準輸入,標準輸出,標準錯誤,父子程序還是共享的。

                            

                                                            圖3   fork()以後開啟my.dat