文件描述符表、文件表、索引結點表


進程打開一個文件,會與三個表發生關聯,分別是:文件描述符表、文件表、索引結點表。

當同一個進程對同一個文件多次使用open時;對一個文件描述符調用dup函數;父進程使用fork創建一個子進程,子進程和上面三個表的關系;當子進程調用exec函數,子進程和上三個表的關系又發生了什么變化;不同的進程打開同一個文件,那么這些進程又是以怎么樣的形式相關聯。本文將解釋這些問題。

 

文件描述符表、文件表、索引結點表存放地點

每個進程都有一個屬於自己的文件描述符表。

文件表存放在內核空間,由系統里的所有進程共享。

索引結點表也存放在內核空間,由所有進程所共享。

了解這個些表的存放位置很重要。

三個表的作用

文件描述符表:該表記錄進程打開的文件。它的表項里面有一個指針,指向存放在內核空間的文件表中的一個表項。它向用戶提供一個簡單的文件描述符,使得用戶可以通過方便地訪問一個文件。

當進程使用open打開一個文件時,內核就會在這個表中添加一個表項。如果對同一個文件打開多次,那么將有多個表項。使用dup時,也會增加一個表項。

文件表:文件表保存了進程對文件讀寫的偏移量。該表還保存了進程對文件的存取權限。比如,進程以O_RDONLY方式打開文件,這將記錄到對應的文件表表項中。

索引結點表:在文件系統中,也是有一個索引結點表的。如下圖所示:

 

 

 

這兩個索引結點表有千絲萬縷的關系。因為內存中的索引結點表的每一個表項都是從文件系統中讀入的,並且兩個索引結點表有一對一的關系。所以,內存中的索引結點表的每一個表項都對應一個具體的文件。

上面所說的三個表的功能,使得三個表緊密地聯系在一起,文件描述符表項有一個指針指向文件表表項,文件表表項有一個指針指向索引結點表表項。

不同的進程打開同一個文件

不同的進程打開同一個文件,那么他們應該有各自對應的文件表表項。因為文件表表項記錄了進程讀寫文件時的偏移量和存取權限。多個進程不可能共享一個文件偏移量。另外他們各自打開文件的權限也可能是不同的,有的是為了讀、有的為了寫,有的為了讀寫。所以,他們應該有不同的文件表表項。

此外,因為是同一個文件,所以,多個進程會共享同一個索引結點表項。即他們的文件表表項指針會指向同一個索引結點

最終,如下圖所示:

 

 

 

使用dup函數復制一個文件描述符

dup函數是用來復制一個文件描述符的。點擊這個鏈接可以看到,復制得到的文件描述符和原描述符共享文件偏移量和一些狀態。所以dup的作用僅僅是復制一個文件描述符表項,而不會復制一個文件表表項。

於是使用dup函數后,有下圖:

 

 

 

dup函數是一個很重要的函數。平時我們在shell里面通過 >  來進行重定向,就是通過dup函數來實現的。

同一個進程多次打開同一個文件

每打開一次同一個文件,內核就會在文件表中增加一個表項。這是因為每次open文件時使用了不同的讀寫權限,而讀寫權限是保存在文件表表項里面的。

所以,效果圖如下所示:

 

 

 

父進程使用fork創建子進程

由於fork一個子進程,子進程將復制父進程的絕大部分東西(除了進程ID、進程的父進程ID、一些時間屬性、文件鎖)。所以子進程復制了父進程的整個文件描述符表。

結果如下圖所示:

 

 

 

進程調用exec后,文件描述符的保留情況

我們經常會在shell中,輸入 < 進行標准輸入重定向。比如$wc < test.c

其大致的實現如下:

if(fork()==0)//child process

{

close(0); //關閉鍵盤這個標准輸入

open(inputFile, O_RDONLY); //返回的文件描述符是最小的未使用的整數,此次就是0,實現了重定向

exec(); //執行exec

}

從上面的例子可以看到執行exec后,文件描述符是會保留的。但有時,可能一個進程有很多個文件描述符,執行exec后,都用不着了。那么此時,應該關閉它。這涉及到一個close-on-exec概念,就是在執行exec時,close(關閉)文件描述符。在默認情況下,執行exec是不關閉的。這里有一個系統調用fcntl可以關閉之。

它的原型為:

int fcntl(int fd,int cmd, … /* int arg */);

第一個參數是文件描述符,第二個參數用來指定是要進行的操作。第三個參數依賴於第二個參數

與本文相關的是操作是 F_GETFD和F_SETFD。其分別用來獲取close-on-exec,設置close-on-exec標識的值。

 可以通過fcntl(fd, F_SETFD, 1);來關閉文件描述符。

即參數arg為0時,不關閉;為1時關閉。

  參考:《UNIX環境高級編程》、《UNIX操作系統設計》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM