(轉(zhuǎn))UNIX IO---再談文件描述符
在C程序中,文件由文件指針或者文件描述符表示。ISO C的標(biāo)準(zhǔn)I/0庫函數(shù)(fopen, fclose, fread,
fwrite, fscanf, fprintf等)使用文件指針,UNIX的I/O函數(shù)(open, close, read, write,
ioctl)使用文件描述符。下面重點(diǎn)來說下,文件描述符是如何工作的。
文件描述符相當(dāng)于一個(gè)邏輯句柄,而open,close等函數(shù)則是將文件或者物理設(shè)備與句柄相關(guān)聯(lián)。句柄是一個(gè)整數(shù),可以理解為進(jìn)程特定的文件
描述符表的索引。先介紹下面三個(gè)概念,后面講下open、close等操作以后,文件和文件描述符產(chǎn)生什么關(guān)系,以及fork后文件描述符的繼承等問題。
文件描述符表 :用戶區(qū)的一部分,除非通過使用文件描述符的函數(shù),否則程序無法對(duì)其進(jìn)行訪問。對(duì)進(jìn)程中每個(gè)打開的文件,文件描述符表都包含一個(gè)條目。
系統(tǒng)文件表 :為系統(tǒng)中所有的進(jìn)程共享。對(duì)每個(gè)活動(dòng)的open, 它都包含一個(gè)條目。每個(gè)系統(tǒng)文件表的條目都包含文件偏移量、訪問模式(讀、寫、or 讀-寫)以及指向它的文件描述符表的條目計(jì)數(shù)。
內(nèi)存索引節(jié)點(diǎn)表: 對(duì)系統(tǒng)中的每個(gè)活動(dòng)的文件(被某個(gè)進(jìn)程打開了),內(nèi)存中索引節(jié)點(diǎn)表都包含一個(gè)條目。幾個(gè)系統(tǒng)文件表?xiàng)l目可能對(duì)應(yīng)于同一個(gè)內(nèi)存索引節(jié)點(diǎn)表(不同進(jìn)程打開同一個(gè)文件)。
1、舉例: 執(zhí)行myfd = open( "/home/lucy/my.dat", O_RDONLY); 以后,上述3個(gè)表的關(guān)系原理圖如下:

圖1
系統(tǒng)文件表包含一個(gè)偏移量,給出了文件當(dāng)前的位置。若2個(gè)進(jìn)程同時(shí)打開一個(gè)文件(如上圖A,B)做讀操作,每個(gè)進(jìn)程都有自己相對(duì)于文件的偏移
量,而且讀入整個(gè)文件是獨(dú)立于另一個(gè)進(jìn)程的;如果2個(gè)進(jìn)程打開同一個(gè)文件做寫操作,寫操作是相互獨(dú)立的,每個(gè)進(jìn)程都可以重寫另一個(gè)進(jìn)程寫入的內(nèi)容。
如果上面進(jìn)程在open以后又執(zhí)行了close()函數(shù),操作系統(tǒng)會(huì)刪除文件描述符表的第四個(gè)條目,和系統(tǒng)文件表的對(duì)應(yīng)條目(若指向它的描述符
表唯一),并對(duì)內(nèi)存索引節(jié)點(diǎn)表?xiàng)l目中的計(jì)數(shù)減1,如果自減以后變?yōu)?,說明沒有其他進(jìn)程鏈接此文件,將索引節(jié)點(diǎn)表?xiàng)l目也刪除,而這里進(jìn)程B也在open這
個(gè)文件,所以索引節(jié)點(diǎn)表?xiàng)l目保留。
2、文件描述符的繼承
通過fork()創(chuàng)建子進(jìn)程時(shí),子進(jìn)程繼承父進(jìn)程環(huán)境和上下文的大部分內(nèi)容的拷貝,其中就包括文件描述符表。
(1)對(duì)于父進(jìn)程在fork()之前打開的文件來說,子進(jìn)程都會(huì)繼承,與父進(jìn)程共享相同的文件偏移量。如下圖所示(0-1-2 表示 標(biāo)準(zhǔn)輸入-輸出-錯(cuò)誤):

圖2 fork()之前打開my.dat
系統(tǒng)文件表位于系統(tǒng)空間中,不會(huì)被fork()復(fù)制,但是系統(tǒng)文件表中的條目會(huì)保存指向它的文件描述符表的計(jì)數(shù),fork()時(shí)需要對(duì)這個(gè)計(jì)數(shù)
進(jìn)行維護(hù),以體現(xiàn)子進(jìn)程對(duì)應(yīng)的新的文件描述符表也指向它。程序關(guān)閉文件時(shí),也是將系統(tǒng)文件表?xiàng)l目內(nèi)部的計(jì)數(shù)減一,當(dāng)計(jì)數(shù)值減為0時(shí),才將其刪除。
(2)相反,如果父進(jìn)程先進(jìn)程fork,再打開my.dat,這時(shí)父子進(jìn)程關(guān)于my.dat
的文件描述符表指向不同的系統(tǒng)文件表?xiàng)l目,也不再共享文件偏移量(fork以后2個(gè)進(jìn)程分別open,在系統(tǒng)文件表中創(chuàng)建2個(gè)條目);但是關(guān)于標(biāo)準(zhǔn)輸入,
標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤,父子進(jìn)程還是共享的。

圖3 fork()以后打開my.dat
本文出自 “淡泊明志,寧靜致遠(yuǎn)” 博客,請(qǐng)務(wù)必保留此出處http://keren.blog.51cto.com/720558/170822
posted on 2009-12-22 11:20 攀升 閱讀(715) 評(píng)論(0) 編輯 收藏 引用 所屬分類: Linux

