天天看點

Linux檔案共享(二)——兩個獨立程序打開同一個檔案

如果兩個獨立程序各自打開了同一檔案,則有圖3-2中所示的安排。我們假定第一個程序使該檔案在檔案描述符3上打開,而另一個程序則使此檔案在檔案描述符4上打開。打開此檔案的每一個程序都得到一個檔案對象,但對一個給定的檔案隻有一個v節點表項。每個程序都有自己的檔案對象的一個理由:這種安排使每個程序都有它自己對該檔案的目前位移量。這種情況不會增加對應的打開檔案引用計數,而會增加dentry的引用。

Linux檔案共享(二)——兩個獨立程式打開同一個檔案

       給出了這些資料結構後,現在對前面所述的操作作進一步說明。

(1) 在完成每一個write後,在檔案表項中的目前檔案位移量即增加所寫的位元組數。如果這使目前檔案位移量超過了目前檔案長度,則在i節點表象中的目前檔案長度被設定為目前檔案位移量(也就是該檔案加長了)。

(2)   如果用o_append标志打開一個檔案,則相應标志也被設定到檔案表項(file對象)的檔案狀态标志中。每次對這種具有填寫标志的檔案執行寫操作時,在檔案表項中的目前檔案位移量首先被設定為i節點表項中的檔案長度。這就使得每次寫的資料都添加到檔案的目前尾端處。

(3)  lseek值修改檔案表項中的目前檔案位移量,沒有進行任何i/o操作。(不影響i節點,隻影響file對象,詳細分析請見lvyilong316部落格:空洞檔案)

(4)  若一個檔案用lseek被定位到檔案目前的尾端,則檔案表項中的目前檔案位移量被設定為i節點表項中的目前檔案長度。

将圖3-2轉化為linux下的具體實作,如下圖所示。

Linux檔案共享(二)——兩個獨立程式打開同一個檔案

注:綠色部分為程序1的私有資源,黃色部分為程序2的私有資源,藍色部分為程序1、程序2的共享資源。

擴充:

(1)用leek定位到目前檔案尾端,在向檔案寫入(write)與使用o_append打開(open)檔案再寫入(write)的差別:

前者是“非原子”操作,假如兩個程序都使用前者的方式向檔案結尾寫入資料,那麼有可能産生這樣的排程序列:

程序a:leek  程序b:leek 程序a:write 程序b:write

第一個程序寫入後,檔案(i節點)的偏移已經改變,第二個程序再寫會覆寫第一個程序剛寫的内容。而是用o_append的open,會使核心每次對檔案寫之前,都将程序的目前偏移量(file對象中的)設定到檔案的尾端處(i節點的目前檔案長度)。

注意:對于多個程序打開同一檔案的情況,每個程序都有它自己的檔案表項(file對象),其中有它自己的檔案位移量,是以對于多個程序讀同一檔案都能正确工作。但是,當多個程序寫同一檔案時,則可能産生預期不到的結果。(可以使用pread,pwrite)。

總結:兩個獨立程序打開同一檔案,對應不同的file對象,每個程序調用close隻影響本程序的“打開檔案計數”(file對象的引用計數)。

繼續閱讀