歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux文件共享-進程與打開文件

Linux支持在不同進程間共享打開文件。為了說明文件共享,先來說明內核用於所有I/O的數據結構。 他們之間的關系決定了在文件共享方面一個進程對另一個進程可能產生的影響。

0.1和文件有關的對象

(1) inode(i節點): 保存一個文件的通用信息,每個inode有一個inode number,在文件系統中,一個inode number能夠唯一地標識一個文件。

(2) dentry(目錄項對象):每個dentry代表路徑中的一個特定部分。保存一個目錄的鏈接信息。個人理解:描述一個文件和一個名字的對應關系。

(3) file(文件對象):保存一個打開的文件與一個進程的關系,文件對象表示進程已經打開的文件 在內存中的表示,該對象不是物理上的文件。它是由相應的open()系統調用創建,由close()系統調用銷毀(只有其引用計數為0時才銷毀)。多個進程可以打開和操作同一個文件,所以同一個文件也可能存在多個對應的文件對象。 它即為apue中所說的“目錄表項”,內涵文件偏移等信息。

0.2和進程有關的對象

(1)  files_struct:每個進程用一個files_struct結構來記錄文件描述符的使用情況,這個結構稱為用戶打開文件表(含有描述符表)。它是進程的私有數據。它即為apue中的“打開文件描述符表”。

(2) fs_struct:fs_struct 結構描述進程與文件系統的關系。

這些對象的關系如下圖所示。


0.3 Apue文件對象解讀

再來看一下apue中描述的關於文件和進程的關系,如下圖( 圖3-1)顯示了進程的三張表之間的關系。該進程有兩個不同的打開文件—一個文件打開為標准輸入(文件表述符0),另一個打開為標准輸出(文件描述符1)。

(1)每個進程在進程表中都有一個記錄項(打開文件描述符表),記錄項中包含有一張打開文件的描述符表,可將其視為一個矢量,每個描述符占用一項。

   每個文件描述符相關連的是:

·       文件描述符標志(close_on_exec)。

·       指向一個文件表項的指針。

注解:這裡描述的即為Linux進程描述符(tast_struct)中的files(files_struct類型)。

(2)內核為所有打開文件維持一張文件表。每個文件表項包含:

·        文件狀態標志(包含讀寫,填寫,同步,非阻塞等)

·        當前文件偏移量

·        指向該文件v節點表項的指針。

注解:這裡描述的“文件表項”即為linux系統下的文件對象(file)。

(3)每個打開的文件都有一個v節點結構。v節點包含了文件類型和對此文件進行各種操作的函數的指針。對於大多數文件,v節點還包括了該文件的i節點。這些信息是再打開文件時從磁盤上讀入內存的。這些文件都是從磁盤讀入內存的,所以可以快速使用這些參數。

注解:這裡描述的v節點,在linux中即為i節點,對應inode對象。

之後我們的討論也主要圍繞這三大對象。      

0.4 引用計數

在我們討論的幾個和文件有關的對象中都存在引用計數,而他們的含義各不相同,理解這些引用計數對我們下面的討論至關重要。

(1) file_struct引用計數:表明共享此結構的進程(線程)數。(我們討論線程共享文件會用到)

(2) fs_struct引用計數:表明共享此結構的進程(線程)數。(我們討論線程共享文件會用到)

(3) file對象引用計數:打開文件引用計數,引用這個file對象描述符數。(dup和fork都會增加這個計數,第一次open會使此計數為1,close會減小此計數,為0時銷毀file對象)

(4) dentry引用計數:每一個計數對應一個file對象。

(5) inode引用計數:每一個計數對應一個dentry。

擴展:

(1)close_on_exec標志

從圖中可見,這個標著在進程的files_struct中, 是一個進程所有文件描述符(文件句柄)的位圖標志,每個比特位對應一個打開的文件描述符,用於確定在調用系統調用execve()時需要關閉的文件描述符,可用fcntl設置。

(2)附錄:i節點結構

struct dinode
{
 ushort di_mode;  /*文件類型+用戶權限*/
 short di_nlink;  /*文件鏈接數*/
 ushort di_uid;  /*屬主用戶id*/
 ushort di_gid;  /*屬主用戶組id*/
 off_t di_size;  /*文件大小*/
 char di_addr[40]; /*文件數據區起點地址*/
 time_t di_atime; /*最後訪問時間*/
 time_t di_mtime; /*最後修改時間*/
 time_t di_ctime; /*創建時間*/
};

Copyright © Linux教程網 All Rights Reserved