1. 程式人生 > >linux檔案描述符,系統開啟檔案和i節點的關係

linux檔案描述符,系統開啟檔案和i節點的關係

首先區分檔案描述符和開啟的檔案

核心維護了三個資料結構

程序級的檔案描述符表(即每個程序一個)

系統級的開啟檔案表(即該表在整個核心中只有一個)

檔案系統的 i-node 表

針對每個程序,核心為其維護一個開啟的檔案描述符表(open file descriptor table),改表的每一項都記錄了單個檔案描述符的相關資訊,如下:

控制檔案描述符的操作的一組標識,目前只定義了一個,即 close-on-exec 標識

對開啟檔案控制代碼的引用

系統為所有開啟的檔案維護了一個系統級別的描述表格(open file description table)。該表的每一項儲存了一個已開啟的檔案的所有相關資訊,包括如下內容:

檔案指標偏移量 (read()和write()修改,以及lseek()修改)

開啟檔案的狀態標識

檔案訪問模式

與訊號驅動I/O相關的設定

指向 i-node 物件的一個指標

這裡有兩個概念要區分

一個是檔案描述符標識,一個是檔案標識。顯然,檔案描述符標識是標識檔案描述符的特性,檔案標識是標識檔案的特性。close-on-exec是檔案描述符的標識。O_APPEND 是檔案標識。並且檔案描述符標識體現在程序檔案描述符表結構中。檔案狀態標識體現在系統開啟檔案描述符表中。

每個檔案系統都有一個i-node結構,包括如下資訊:

檔案型別和許可權,例如regular file,socket等

該檔案持有的所有鎖

其他各種特性,比如檔案大小,時間戳等等

1. 對同一個檔案描述符的讀和寫位置共享。

測試程式碼:
char buf[128];
int main(int argc,char *argv[])
{
        char *s = "test";
        int fd = open("test.txt",O_RDWR);
        if(fd == -1)
        {
                perror("open test.txt failure");
                exit(EXIT_FAILURE);
        }

        int
readNum = read(fd,buf,3); write(fd,s,4); if(-1 == close(fd)) { perror("close failure"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
測試條件,test.txt檔案的初始內容為123456789
測試結果:程式執行之後test.txt檔案的內容為123test89
分析:

1. 對 test.txt 進行了讀寫開啟

2. 先對test.txt 讀3個位元組,所以此時fd的偏移量應該是3

3. 接著對fd寫4個位元組,根據最終的輸出結果可以知道此時是從偏移量為3的地方開始寫的,所以對於同一個檔案描述符來說,讀寫位置是共享的。

2. 同一個程序多次開啟同一個檔案

測試程式碼:
int main(int argc,char *argv[])
{
        char buf[10];
        char *s = "test";
        int fd1 = open("test.txt",O_RDWR);

        int readNum = read(fd1,buf,3);


        int fd2 = open("test.txt",O_RDWR);
        write(fd2,s,4);
}
測試條件,test.txt檔案的初始內容為123456789
測試結果:程式執行之後test.txt檔案的內容為test56789
分析:

1. 對 test.txt 進行了第一次open操作得到fd1

2. 先通過fd1對test.txt 讀3個位元組,所以此時fd1所對應的偏移量應該是3

3. 接著對test.txt進行了第二次open操作,得到了fd2,

4. 通過fd2對test.txxt寫4個位元組,根據最終的輸出結果可以知道此時是從偏移量為0的地方開始寫的

5. 綜上所述,如果對同一個檔案開啟多次,那麼這些檔案描述符所對應的核心結構是獨立的。

6、從上面的結果也可以看出來,即使是同一個檔案,如果我們打開了多次,那麼核心也會維護多個開啟檔案表項。