文件系統(tǒng)頁課件_第1頁
文件系統(tǒng)頁課件_第2頁
文件系統(tǒng)頁課件_第3頁
文件系統(tǒng)頁課件_第4頁
文件系統(tǒng)頁課件_第5頁
已閱讀5頁,還剩135頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第六章 文件系統(tǒng)操作系統(tǒng) 1第六章 文件系統(tǒng)操作系統(tǒng) 16.1 概述(1)字段 數(shù)據(jù)的基本單位,字段又可稱為域或數(shù)據(jù)項(xiàng)。不可分隔的字段含有一個(gè)簡(jiǎn)單的值,如姓名、日期、傳感器讀入的值等。字段的特征可由長(zhǎng)度和數(shù)據(jù)類型表示。字段可以是固定長(zhǎng)度的或可變長(zhǎng)度的。(2) 記錄 能被某些應(yīng)用程序處理的相關(guān)字段的集合。例如,雇員記錄可包括姓名、社會(huì)保險(xiǎn)號(hào)、工種、雇用日期等。記錄可以是固定長(zhǎng)度或可變長(zhǎng)度的。26.1 概述(1)字段 數(shù)據(jù)的基本單位,字段又可稱為域或數(shù)(3)文件 相同記錄的集合,可以用名字來引用,并可以產(chǎn)生和刪除。存取控制通常施加到文件這一級(jí)。在某些復(fù)雜的系統(tǒng)中,存取控制能施加到記錄級(jí),甚至字段級(jí)

2、。(4) 數(shù)據(jù)庫 相關(guān)數(shù)據(jù)的集合。數(shù)據(jù)庫的基本特征是在數(shù)據(jù)元素之間存在明顯的關(guān)系。(5) 文件管理系統(tǒng) 文件管理系統(tǒng)是為用戶和用戶程序在使用文件時(shí)提供服務(wù)的系統(tǒng)軟件集合。一般用戶或應(yīng)用程序存取文件時(shí)必須通過文件管理程序。文件管理系統(tǒng)避免了用戶或程序設(shè)計(jì)員必須為每種應(yīng)用都開發(fā)特定目的軟件,提供了控制系統(tǒng)中最重要財(cái)富文件的方法。3(3)文件 相同記錄的集合,可以用名字來引用,并可以產(chǎn)生和2 文件的組織和存取 文件組織指的是由存取方法決定的記錄的邏輯結(jié)構(gòu)。在外存中文件的物理組織取決于組塊策略和文件分配策略。 在選擇文件組織方法時(shí),有幾個(gè)重要的參考標(biāo)準(zhǔn):存取快速更新容易節(jié)省存儲(chǔ)單元管理簡(jiǎn)單可靠性 在圖

3、6-1中描述了普通文件的組織方法:42 文件的組織和存取 文件組織指的是由存取方法決定的記錄可變長(zhǎng)度記錄可變字段集合時(shí)間序排列(a)堆文件關(guān)鍵字字段(b)順序文件固定長(zhǎng)度記錄固定次序、固定集合的字段按關(guān)鍵字的順序(c)索引順序文件索引鏈索引指針主文件溢出指針溢出文件(d)索引文件詳盡索引1詳盡索引2部分索引1可變長(zhǎng)度記錄主文件(e)散列文件f主文件溢出文件keyHash函數(shù)5可變長(zhǎng)度記錄(a)堆文件關(guān)鍵字字段(b)順序文件固定長(zhǎng)度記錄(1)堆(Pile)數(shù)據(jù)根據(jù)到達(dá)時(shí)間的順序收集起來,每一個(gè)記錄包括一堆集中到達(dá)的數(shù)據(jù)。堆的目的只是簡(jiǎn)單地聚集大量的數(shù)據(jù),并存儲(chǔ)它。當(dāng)收集數(shù)據(jù)時(shí)需先存儲(chǔ)再處理或數(shù)據(jù)

4、不容易組織時(shí),就可用到堆。(2) 順序文件使用固定格式的記錄。所有記錄的長(zhǎng)度相等,含有相同個(gè)數(shù)、特定次序的固定長(zhǎng)度字段。由于每一個(gè)字段的長(zhǎng)度和位置是已知的,所以僅僅需要存儲(chǔ)字段的值。每個(gè)字段的字段名和長(zhǎng)度歸于文件結(jié)構(gòu)的屬性。順序文件的另一種組織方法是采用鏈接表。6(1)堆(Pile)數(shù)據(jù)根據(jù)到達(dá)時(shí)間的順序收集起來,每一個(gè)記(3) 索引順序文件索引順序文件維護(hù)了順序文件的關(guān)鍵字特征:記錄以關(guān)鍵字字段的順序組織。此外,還增加了兩個(gè)新的特征:支持隨機(jī)存取的文件索引和溢出文件。在索引文件中的每個(gè)記錄包括兩個(gè)字段:一個(gè)是與主文件關(guān)鍵字相同的關(guān)鍵字字段。另一個(gè)是指向主文件的指針。 (4) 索引文件 需要使

5、用多索引的結(jié)構(gòu)。詳盡的索引為主文件中的每一個(gè)記錄建立一個(gè)入口項(xiàng)。部分索引對(duì)感興趣字段的記錄建立入口項(xiàng)。索引本身組織成一個(gè)順序文件以便容易搜索。7(3) 索引順序文件索引順序文件維護(hù)了順序文件的關(guān)鍵字特征:(5) 散列文件直接存取的散列文件使用對(duì)關(guān)鍵字值的散列。散列文件經(jīng)常用于需要快速存取的場(chǎng)合。文件包括固定長(zhǎng)度的記錄,應(yīng)用程序一般一次存取一個(gè)記錄。目錄、調(diào)度表和名字表等都可使用散列文件。8(5) 散列文件直接存取的散列文件使用對(duì)關(guān)鍵字值的散列。散列3 文件系統(tǒng)結(jié)構(gòu) 設(shè)備驅(qū)動(dòng)程序負(fù)責(zé)對(duì)設(shè)備的啟動(dòng)I/O操作,處理I/O請(qǐng)求完成后的工作。 上一層是基本文件系統(tǒng),或稱物理I/O層,這一層是與計(jì)算機(jī)系統(tǒng)

6、外部環(huán)境的主要接口 基本I/O管理主要負(fù)責(zé)所有文件I/O的初始化和結(jié)束工作。在這一層,維護(hù)處理設(shè)備I/O、調(diào)度和文件的控制結(jié)構(gòu)。I/O緩沖區(qū)的分配及外存的定位工作也在這一層完成。 邏輯I/O使用戶和應(yīng)用程序能夠存取記錄。 最接近用戶的文件系統(tǒng)層是存取方法層,其提供了用戶與文件系統(tǒng)和存儲(chǔ)數(shù)據(jù)的設(shè)備之間的標(biāo)準(zhǔn)接口。93 文件系統(tǒng)結(jié)構(gòu) 設(shè)備驅(qū)動(dòng)程序負(fù)責(zé)對(duì)設(shè)備的啟動(dòng)I/O操作堆順序索引順序索引散列邏輯I/O基本I/O管理基本文件系統(tǒng)磁帶驅(qū)動(dòng)器磁盤驅(qū)動(dòng)器圖6-2文件系統(tǒng)軟件結(jié)構(gòu)用戶程序10堆順序索引順序索引散列邏輯I/O基本I/O管理基本文件系統(tǒng)磁6.2文件目錄1 目錄的內(nèi)容 目錄含有文件的信息,包括文

7、件的屬性、位置和屬主等。目錄本身也是文件,各種文件管理例行程序要通過操作系統(tǒng)存取目錄文件。 目錄提供了為用戶和應(yīng)用程序所知的文件名和文件實(shí)體本身的映射。 所有的系統(tǒng)都要處理不同類型的文件和不同的文件組織,因此也要提供此類文件信息。 文件的位置和大小。 在共享系統(tǒng)中,提供用戶對(duì)文件的存取控制。 文件和記錄文件歷史的信息。116.2文件目錄1 目錄的內(nèi)容 目錄含有文件的信息,包括(1)基本信息 文件名: 在一個(gè)特定的目錄中具有唯一性。 文件類型: 例如文本文件,二進(jìn)制文件,目標(biāo)模塊等。 文件組織: 系統(tǒng)所支持的不同組織形式。(2)地址信息 起始地址: 文件存放在外存的起始物理地址(例如:柱面號(hào)、磁

8、道號(hào)或在磁盤上的塊號(hào))。 已使用大?。?當(dāng)前文件的大小,以字節(jié)、字或塊計(jì)。(3)存取控制信息 文件主: 擁有文件的控制權(quán)。文件主能授予和取消其他用戶對(duì)文件的存取權(quán)和改變這些權(quán)限。 允許的操作: 控制讀、寫、執(zhí)行和在網(wǎng)上的傳輸?shù)取?4)使用信息 創(chuàng)建日期: 文件首次存放在目錄中的時(shí)間。 讀時(shí)間: 最后一次讀文件記錄的時(shí)間。 修改時(shí)間: 最后一次更新、插入或刪除記錄的時(shí)間。12(1)基本信息126.2.2 目錄的結(jié)構(gòu)對(duì)目錄操作的類型:搜索: 搜索目錄以找到對(duì)應(yīng)于文件的目錄項(xiàng)。創(chuàng)建文件: 將目錄項(xiàng)加到目錄中。刪除文件: 從目錄中移去一個(gè)目錄項(xiàng)。列目錄: 可以要求列出全部或部分目錄內(nèi)容。使用兩級(jí)目錄。

9、在這種情況下,系統(tǒng)有一個(gè)主目錄,并為每一個(gè)用戶設(shè)置一個(gè)目錄。 層次結(jié)構(gòu)或稱樹型結(jié)構(gòu)。系統(tǒng)中有一個(gè)主目錄,在它之下有一些用戶目錄,每一個(gè)用戶目錄也同樣允許有子目錄和文件。136.2.2 目錄的結(jié)構(gòu)對(duì)目錄操作的類型:136.3 文件存儲(chǔ)資源分配(1)預(yù)分配和動(dòng)態(tài)分配 預(yù)分配的策略需要在創(chuàng)建文件時(shí)說明文件的最大長(zhǎng)度。對(duì)于很多的應(yīng)用,要可靠地估計(jì)文件的長(zhǎng)度如果不是不可能的,也是很困難的。用戶和應(yīng)用程序只能傾向于過高估計(jì)文件的長(zhǎng)度以便不會(huì)用完分配給文件的空間。從存儲(chǔ)分配的角度看,這明顯是浪費(fèi)的。相反,動(dòng)態(tài)分配不存在這個(gè)缺點(diǎn),這種方法在需要時(shí)才給文件分配空間。146.3 文件存儲(chǔ)資源分配(1)預(yù)分配和動(dòng)態(tài)

10、分配 預(yù)分配的策略(2)分區(qū)大小 1) 連續(xù)的空間提高了操作性能。 2) 具有大量的小分區(qū)增加了管理存儲(chǔ)分配信息表的大小。 3) 具有固定大小的分區(qū)(如,以塊為單位)可簡(jiǎn)化存儲(chǔ)空間的算法。 4) 具有可變大小或固定的小尺寸的分區(qū)可以減少存儲(chǔ)空間的浪費(fèi)。15(2)分區(qū)大小 1) 連續(xù)的空間提高了操作性能。15兩個(gè)主要的選擇方案可變長(zhǎng)度、連續(xù)的大分區(qū): 性能較好。可變長(zhǎng)度避免浪費(fèi)存儲(chǔ)空間,文件分配表也較小。塊: 小而固定長(zhǎng)度的分區(qū),靈活性大。但存儲(chǔ)分配需要較大的表或復(fù)雜的結(jié)構(gòu)。存儲(chǔ)塊即需即分配,但塊間就不一定相鄰??勺冮L(zhǎng)度分區(qū)需要考慮空閑區(qū)的碎片問題。 首次適應(yīng)法: 選擇第一個(gè)足夠大小的連續(xù)空閑塊

11、組。 最佳適應(yīng)法: 在所有滿足大小要求的空閑塊組中選擇最小的一組。 循環(huán)首次適應(yīng)法: 選擇離該文件的前次分配物理位置最近的滿足大小要求的空閑塊組。16兩個(gè)主要的選擇方案可變長(zhǎng)度、連續(xù)的大分區(qū): 性能較好??勺冮L(zhǎng)(4)空閑存儲(chǔ)空間管理位表這種方法是每一二進(jìn)制位對(duì)應(yīng)一個(gè)磁盤塊。二進(jìn)制位為0表示一個(gè)空閑塊,位值為1表示該塊已被使用。位表所具有的優(yōu)點(diǎn)是查找一個(gè)或一組連續(xù)的空閑塊比較方便。位表已是盡可能地小,因此可以全部放入主存中。.空閑分區(qū)鏈 空閑分區(qū)可以用指針連在一起,還需要一個(gè)空閑分區(qū)的長(zhǎng)度信息。索引 索引方法將空閑存儲(chǔ)區(qū)當(dāng)作文件一樣處理,像文件分配那樣使用索引表。在索引表上的每一項(xiàng)對(duì)應(yīng)磁盤上的每

12、一個(gè)空閑分區(qū)。17(4)空閑存儲(chǔ)空間管理位表176.4文件的系統(tǒng)調(diào)用6.4.1 文件的創(chuàng)建、打開、關(guān)閉和取消1.文件的創(chuàng)建 fd=creat(pathname,mode); int fd, mode; char *pathname; pathname是要?jiǎng)?chuàng)建文件的帶路徑的文件名。 mode是以二進(jìn)制的位值為該文件設(shè)置的存取控制權(quán)限。其低9位以3位為一組,由高至低位分別表示文件主,文件主同組用戶和其他用戶對(duì)該文件是否擁有讀、寫、執(zhí)行權(quán)限。mode中還可設(shè)置如下控制位: 01000文件使用后仍保留在盤交換區(qū)上。 04000用戶執(zhí)行本文件時(shí)將其有效用戶標(biāo)識(shí)數(shù)u_uid設(shè)置為文件主標(biāo)識(shí)數(shù),該特性一般為

13、超級(jí)用戶所使用。 第1215位為文件類型位。 fd中存放文件創(chuàng)建成功后系統(tǒng)返回的整數(shù)值,稱為打開文件標(biāo)識(shí)數(shù)(或稱描述字)。186.4文件的系統(tǒng)調(diào)用6.4.1 文件的創(chuàng)建、打開、關(guān)閉和取2.文件的打開 fd=open (pathname,flags); int fd, flags; char *pathname; pathname和fd的意義同creat調(diào)用中同名變量。 flags表示本次打開后要對(duì)文件進(jìn)行的操作,可取的值及意義列舉如下: O_RDONLY(0) 對(duì)文件進(jìn)行讀操作 O_WRONLY(1) 對(duì)文件進(jìn)行寫操作。 O_RDWR (2) 對(duì)文件既可以讀也可以寫。 O_NDELAY (4)

14、打開管道文件時(shí)是否要等待。 O_APPEND (8) 對(duì)文件進(jìn)行添加寫操作。 要使用以上常數(shù),應(yīng)包含fcntl.h文件。 應(yīng)該遵循最小存取權(quán)原理。192.文件的打開 fd=open (pathname3. 文件的關(guān)閉4. 文件的聯(lián)接、解除聯(lián)接和刪除 close(fd); 為名為name1的文件再起一個(gè)新的名,可使用系統(tǒng)調(diào)用: link(name1, name2); 要取消某文件的一個(gè)文件名,則可用系統(tǒng)調(diào)用: unlink(pathname); 利用link和unlink調(diào)用可以改變文件的名: link(name1, name2); unlink(name1); 相當(dāng)于UNIX命令: mv na

15、me1 name2 unlink調(diào)用僅僅使其聯(lián)接數(shù)減去1。當(dāng)文件僅剩下一個(gè)名時(shí),unlink調(diào)用取消這一文件名后再將該文件從系統(tǒng)中刪去。203. 文件的關(guān)閉4. 文件的聯(lián)接、解除聯(lián)接和刪除 6.4.2文件的讀寫 n=read(fd,buf,nbytes); n=write(fd,buf,nbytes); int fd,n; unsigned nbyte; char *buf; fd為先前已打開文件的描述字, nbyte是欲讀、寫的字節(jié)數(shù)。 對(duì)于讀,buf是讀出的文件信息應(yīng)送至的目標(biāo)區(qū)始址;對(duì)于寫,buf是要寫入文件的信息源區(qū)首址。 n是調(diào)用返回值,表示實(shí)際讀出和或?qū)嶋H寫入的字節(jié)數(shù)。n的值可能不

16、等于nbytes的值。如不相等,對(duì)于讀,0nnbytes時(shí),表示已讀到了文件尾,n=-1時(shí),表示讀操作出錯(cuò)。對(duì)于寫,nnbyte或n=-1時(shí)都表示寫出錯(cuò)。216.4.2文件的讀寫 n=read(fd,buf,三個(gè)特殊的文件 一般在進(jìn)程創(chuàng)建后就已處于打開的狀態(tài),它們是: 0號(hào) 標(biāo)準(zhǔn)讀文件代表鍵盤輸入 1號(hào) 標(biāo)準(zhǔn)寫文件代表屏幕顯示 2號(hào) 標(biāo)準(zhǔn)錯(cuò)誤輸出文件,是程序的運(yùn)行時(shí)的出錯(cuò)信息,也寫至屏幕上,但在shell命令中不能直接用I/O轉(zhuǎn)向符“”將標(biāo)準(zhǔn)錯(cuò)誤輸出轉(zhuǎn)向至一個(gè)文件。22三個(gè)特殊的文件 一般在進(jìn)程創(chuàng)建后就已處于打開的狀態(tài),它#define BUFSIZE 1024main( ) char buf

17、 BUFSIZE; int n; while (n=read(0, buf, BUFSIZE)0) write (1, buf, n); UNIX的文件讀寫是通過緩存進(jìn)行,而緩存的大小為1024(或它的倍數(shù)),故一次讀寫的字節(jié)數(shù)以BUFSIZE為宜。 下面是一個(gè)將標(biāo)準(zhǔn)輸入文件復(fù)制到標(biāo)準(zhǔn)輸出文件的程序,執(zhí)行該程序的效果相當(dāng)于不帶任何參數(shù)的cat命令。23#define BUFSIZE 1024 下面是一個(gè)將標(biāo)6.4.3 調(diào)整文件讀寫位置lseek read和write系統(tǒng)調(diào)用提供了文件順序讀、寫功能,但如要從文件中的指定位置起讀或?qū)?,就要使用改變文件讀寫指針的系統(tǒng)調(diào)用lseek,其調(diào)用格式為:

18、lseek (fd, offset, whence); int fd, whence; long offset; offset和whence配合起來決定調(diào)整到文件中的一個(gè)新位置。offset為字節(jié)偏移值,whence為參考點(diǎn)。whence取值及意義如下所列: 0: 讀寫位置的參考點(diǎn)為文件的起始位置。 1: 讀寫位置的參考點(diǎn)為當(dāng)前的讀、寫位置。 2: 讀寫位置的參考點(diǎn)為文件尾。 分別表達(dá)絕對(duì)位置、當(dāng)前相對(duì)位置和文件尾相對(duì)位置。246.4.3 調(diào)整文件讀寫位置lseek read和wr6.4.4 創(chuàng)建任何類型文件mknod 目錄、有名管道和特別文件只能用mknod創(chuàng)建: #include #inc

19、lude int mknod (pathname, mode, device); char *pathname; /*文件名*/ int mode, device;/*文件的屬性和權(quán)限模式,設(shè)備號(hào)*/ 在創(chuàng)建文件、目錄和有名管道時(shí),參數(shù)device被忽略,但在創(chuàng)建特別文件時(shí)要提供設(shè)備號(hào)參數(shù)。 普通用戶可以用mknod創(chuàng)建一個(gè)有名管道,但只有超級(jí)用戶可以用mknod創(chuàng)建文件、目錄和特別文件。對(duì)于普通用戶,mkdir只有shell命令,沒有系統(tǒng)調(diào)用(Linux有)。256.4.4 創(chuàng)建任何類型文件mknod 目錄、有名管道 6.4.5 其他的文件系統(tǒng)調(diào)用 1.改變文件的權(quán)限chmod 本調(diào)用功能是

20、改變一個(gè)文件或目錄的許可權(quán),調(diào)用格式為 chmod (pathname, mode); char *pathname; int mode;mode的二進(jìn)制位定義同creat系統(tǒng)調(diào)用。2.復(fù)制文件描述字dup 本調(diào)用為一個(gè)已打開的文件再分配一個(gè)新的文件描述字,使多個(gè)文件描述字可與同一個(gè)文件相聯(lián)系,在構(gòu)造shell的管道線時(shí)這個(gè)調(diào)用很重要。調(diào)用格式為 newfd=dup (fd); int fd, newfd; 執(zhí)行本調(diào)用時(shí),核心為已打開的文件fd再分配一個(gè)在打 開文件表中最小可用的文件描述字,并返回給執(zhí)行進(jìn)程。26 6.4.5 其他的文件系統(tǒng)調(diào)用 1.改變文件的權(quán)限chmo4. 查詢文件的狀態(tài)s

21、tat與fstat 本調(diào)用功能使返回文件的類型、大小、所有者、存取權(quán)限,聯(lián)接數(shù)等信息。這些信息是從文件的索引節(jié)點(diǎn)中讀出來的。調(diào)用格式有兩種: stat (pathname, buf); fstat (fd, buf); char *pathname; struct stat *buf; int fd; 在上面兩個(gè)系統(tǒng)調(diào)用中,前一個(gè)調(diào)用所指文件是以UNIX的路徑名形式給出,因此能返回文件系統(tǒng)中存在的文件狀態(tài),后一個(gè)調(diào)用是以文件描述字的形式給出,故只能用于已打開的文件。后一種調(diào)用執(zhí)行的速度要比前一種快。返回的文件狀態(tài)存放在stat類型的結(jié)構(gòu)中。274. 查詢文件的狀態(tài)stat與fstat 本調(diào)用功

22、能使返回5. 文件控制fcntl 對(duì)已打開的文件進(jìn)行控制 fcntl (fd, cmd, arg); int fd, cmd, arg; cmd為對(duì)文件的控制模式,主要的取值及意義有: F_DUPFD: 返回大于或等于arg變量所給出描述字的新的描述字。本功能類似于dup系統(tǒng)調(diào)用。 F_GETFL: 獲取fd所對(duì)應(yīng)文件的狀態(tài)信息,這個(gè)信息對(duì)應(yīng)于open系統(tǒng)調(diào)用的flags。 F_SETFL: 將fd所對(duì)應(yīng)文件的狀態(tài)設(shè)置成arg參數(shù)的值。但不能改變O_RDONLY、O_WRONLY和O_RDWR標(biāo)志,只能設(shè)置O_NDELAY和O_APPEND。285. 文件控制fcntl 對(duì)已打開的文件進(jìn)行控制

23、28例:設(shè)置打開文件的O_APPEND標(biāo)志 為了不影響其他任何標(biāo)志,先要獲取文件狀態(tài),再寫回。#include int set append (fd)int fd; int flag; flags=fcntl (fd, F_GETFL, 0); return (fcntl (fd, F_SETFL, flags|O_APPEND); 29例:設(shè)置打開文件的O_APPEND標(biāo)志 為了不影響其他7. 設(shè)置文件權(quán)限屏蔽字 umask調(diào)用可以設(shè)置或改變進(jìn)程所創(chuàng)建文件的屏蔽字。例如: umask(002); fd=creat(”tempf”, 0666); 盡管creat所創(chuàng)建的tempf文件對(duì)所有的用

24、戶都是可讀可寫的,但由于先調(diào)用了umask(002),使文件主和與文件主同組用戶以外的其他用戶的寫權(quán)限被清除了。 用umask設(shè)置的屏蔽字不影響chmod系統(tǒng)調(diào)用,故用chmod可以將文件權(quán)限置成任何期望的值。307. 設(shè)置文件權(quán)限屏蔽字 umask調(diào)用可以設(shè)置或改變6.5 文件的標(biāo)準(zhǔn)子例程標(biāo)準(zhǔn)I/O的概念 文件基本操作的系統(tǒng)調(diào)用提供的只是字節(jié)序列方式的最基本的功能,不能完成任何格式轉(zhuǎn)化。為了提供功能更強(qiáng)和使用更方便的輸入和輸出操作,UNIX系統(tǒng)提供了標(biāo)準(zhǔn)I/O庫。例如 scanf、printf、getchar和putchar等。 標(biāo)準(zhǔn)I/O庫主要通過用戶態(tài)空間的自動(dòng)緩沖機(jī)構(gòu)以及數(shù)據(jù)類型轉(zhuǎn)化和

25、格式化的輸入輸出,提供了效率高、功能強(qiáng)和可移植的文件訪問或字符串處理功能。 在UNIX的標(biāo)準(zhǔn)I/O庫中,通過一個(gè)FILE類型結(jié)構(gòu)建立與打開文件的聯(lián)系,稱為流(stream)316.5 文件的標(biāo)準(zhǔn)子例程標(biāo)準(zhǔn)I/O的概念 文件基本操作的在頭文件stdio.h中定義的FILE結(jié)構(gòu)typedef struct _iobuf unsigned char *_ptr;緩沖區(qū)內(nèi)下一字符地址 int _cnt;緩沖區(qū)中_ptr所指位置后剩余字符數(shù) unsigned char *_base;緩沖區(qū)起始地址 char _flag;存取方式,如讀或/和寫 char _file;文件描述字 FILE; file用于存

26、放打開文件的描述字 輸出的字節(jié)數(shù)據(jù)逐個(gè)放入緩沖區(qū)中,并相應(yīng)地調(diào)整_ptr和_cnt之值。如果緩沖區(qū)存滿了,例行程序再通過系統(tǒng)調(diào)用write把緩沖區(qū)內(nèi)容寫入_file指示的文件中。 輸入例行程序從緩沖區(qū)中讀數(shù)據(jù),當(dāng)緩沖區(qū)空了時(shí),就通過系統(tǒng)調(diào)用read從文件中再讀入一個(gè)緩沖區(qū)的數(shù)據(jù)。32在頭文件stdio.h中定義的FILE結(jié)構(gòu)typedef struct _iobuf buffer _base _ptr _cnt _flag -flags _file -fd33struct _iobuf331 流文件的打開和關(guān)閉(1) 流文件的打開 include FILE *fp; fp=fopen (pat

27、hname, type); char *pathname, *type; 如果打開成功,把它與一個(gè)流聯(lián)系起來,并返回標(biāo)識(shí)該流的FILE結(jié)構(gòu)的指針。如fopen失敗,返回NULL。參數(shù)type可取下列的基本值: r 打開文件用于只讀。 w 建立文件或把已存在文件截為空文件,用于只寫。 a 打開文件用于文件尾的追加寫。 在上述參數(shù)后各加上一個(gè)”+”,表示修改模式,即可讀可寫,但這種模式有較多限制,特別是在寫操作后不能立即進(jìn)行讀操作,除非中間插入了后面介紹的fseek和rewind兩個(gè)調(diào)整流文件讀寫指針的操作。341 流文件的打開和關(guān)閉(1) 流文件的打開 i 用fopen建立的一個(gè)文件以默認(rèn)值06

28、66作為其控制權(quán)限,這使所有的用戶都能讀寫該文件。如果要以其他值作為控制權(quán)限,則可以先用系統(tǒng)調(diào)用umask改變進(jìn)程的權(quán)限屏蔽字。 與0#,1#,2#三個(gè)標(biāo)準(zhǔn)的打開文件描述字相聯(lián)系,標(biāo)準(zhǔn)I/O庫提供了三個(gè)不需要打開的流,并用下列的FILE指針標(biāo)識(shí): stdin標(biāo)準(zhǔn)輸入流 stdout標(biāo)準(zhǔn)輸出流 stderr錯(cuò)誤輸出流35 用fopen建立的一個(gè)文件以默認(rèn)值0666作為其控制權(quán)(2) 流文件的關(guān)閉 fclose(fp); 該命令刷新與文件相關(guān)的緩沖區(qū),關(guān)閉已打開的文件并釋放FILE結(jié)構(gòu)。如果不顯式執(zhí)行該命令,進(jìn)程運(yùn)行結(jié)束后關(guān)閉所有打開的流文件。36(2) 流文件的關(guān)閉 fclose(fp);363

29、 流文件的讀寫 n=fread(buf,size,nitems,fp); n=fwrite(buf,size,nitems,fp); int n,size,nitems; char *buf; FILE *fp; fread從fp指定的輸入流文件中將nitems個(gè)大小為size的數(shù)據(jù)對(duì)象讀入buf所指向的存儲(chǔ)區(qū)中,返回值n給出了成功讀出的數(shù)據(jù)對(duì)象個(gè)數(shù)。 fwrite將nitems個(gè)大小為size的數(shù)據(jù)對(duì)象從buf所指的存儲(chǔ)區(qū)寫到fp所指定的輸出流文件中。返回值n給出了實(shí)際寫入的數(shù)據(jù)對(duì)象個(gè)數(shù)。 實(shí)際使用時(shí),數(shù)據(jù)對(duì)象的大小size往往用sizeof(struct struct_name)函數(shù)代替。

30、這兩個(gè)流操作可以在二進(jìn)制文件和buf之間傳送任何數(shù)據(jù)結(jié)構(gòu)的內(nèi)容,返回值nnitems 的情況與系統(tǒng)調(diào)用read和write相似。373 流文件的讀寫 n=fread(buf,size,ni下面比較一下循環(huán)執(zhí)行每次寫一個(gè)字節(jié)的系統(tǒng)調(diào)用 write (fd, buf, 1)與每次寫一個(gè)字節(jié)的流文件操作 fwrite (buf, 1, 1, fp)兩者的執(zhí)行效率,假定塊設(shè)備的系統(tǒng)緩沖區(qū)大小和流文件的用戶態(tài)空間緩沖區(qū)大小都是1024字節(jié)。循環(huán)執(zhí)行系統(tǒng)調(diào)用write(fd, buf, 1) 時(shí),每次調(diào)用向文件輸出一個(gè)字節(jié),但由于塊設(shè)備讀寫是通過系統(tǒng)緩沖區(qū)進(jìn)行的,故1024次寫調(diào)用才需要一次實(shí)際設(shè)備I/O

31、操作,但需要1024次從用戶態(tài)轉(zhuǎn)換到核心態(tài)和從核心態(tài)轉(zhuǎn)回用戶態(tài)的開銷。循環(huán)執(zhí)行流文件操作fwrite(buf, 1, 1, fp) 時(shí),每次操作向用戶態(tài)空間的流文件緩沖區(qū)寫入一個(gè)字節(jié),1024次寫操作填滿該緩沖區(qū)后才發(fā)出一次write系統(tǒng)調(diào)用,轉(zhuǎn)換到核心態(tài),并進(jìn)行一次實(shí)際的設(shè)備I/O操作。因此兩種方法的設(shè)備I/O時(shí)間花費(fèi)是一樣的,主要差別是流文件操作用1024次用戶態(tài)函數(shù)的調(diào)用和返回的開銷代替了直接使用系統(tǒng)調(diào)用時(shí)1024次用戶態(tài)與核心態(tài)之間的切換。38下面比較一下循環(huán)執(zhí)行每次寫一個(gè)字節(jié)的系統(tǒng)調(diào)用38 在實(shí)際系統(tǒng)中,一次函數(shù)調(diào)用所費(fèi)的時(shí)間比用戶態(tài)與核心態(tài)之間的切換所費(fèi)的時(shí)間少得多,故當(dāng)不是以整塊

32、的方法輸入或輸出數(shù)據(jù)時(shí),使用流文件操作比使用系統(tǒng)調(diào)用效率高很多。 圖6-3描述了流文件操作與系統(tǒng)調(diào)用之間的關(guān)系。 值得注意的是fread與fwrite這種二進(jìn)制數(shù)據(jù)的讀寫方法與具體機(jī)器的數(shù)據(jù)內(nèi)部存儲(chǔ)方法(如一個(gè)字的高、低位字節(jié)次序)有關(guān),所以在一臺(tái)機(jī)器上寫入的數(shù)據(jù),在另一臺(tái)機(jī)器可能讀不出來,或讀出的數(shù)據(jù)與原先寫入的不同。要避免這類問題,就要用后面介紹的格式輸入和輸出操作。39 在實(shí)際系統(tǒng)中,一次函數(shù)調(diào)用所費(fèi)的時(shí)間比用戶態(tài)與核心態(tài)圖6-3流文件操作與系統(tǒng)調(diào)用間的關(guān)系用戶態(tài)與核心態(tài)切換用戶程序標(biāo)準(zhǔn)I/O庫核心程序流文件操作用戶態(tài)空間核心態(tài)空間塊設(shè)備讀寫塊設(shè)備驅(qū)動(dòng)系統(tǒng)調(diào)用用戶程序fread ( )f

33、write ( )文件卷用戶態(tài)緩沖區(qū)read ( )write ( )核心態(tài)緩沖區(qū)40圖6-3流文件操作與系統(tǒng)調(diào)用間的關(guān)系用用戶程序標(biāo)準(zhǔn)I/O庫核3 調(diào)整和獲取流文件的讀寫位置fseek (fp, offset, whence); rewind (fp); position = ftell (fp); FILE *fp; long offset, position; int whence; fseek的第二、三個(gè)參數(shù)的意義與設(shè)置方法與系統(tǒng)調(diào)用seek一樣。 rewind例行程序?qū)⑽募x寫位置指針調(diào)整到文件首。這相當(dāng)于執(zhí)行前一個(gè)例行程序: fseek (fp, 0L, 0)。 ftell返回流中

34、的當(dāng)前位置。413 調(diào)整和獲取流文件的讀寫位置fseek (fp, off4 格式輸入與輸出除前面介紹的不經(jīng)格式轉(zhuǎn)化的二進(jìn)制數(shù)據(jù)輸入輸出外,標(biāo)準(zhǔn)I/O庫還提供了能進(jìn)行格式轉(zhuǎn)化的I/O例行程序。用戶可以直接觀察存儲(chǔ)在文件中或顯示在屏幕上的數(shù)據(jù),而且這類操作是與機(jī)器特征無關(guān)的。如果用戶要從鍵盤上輸入數(shù)據(jù),那么帶格式轉(zhuǎn)化的輸入一般是唯一的方法。 fscanf (fp, format , arg1, arg2, argn ); fprintf (fp, format , arg1, arg2, argn ); FILE *fp; char *format;424 格式輸入與輸出除前面介紹的不經(jīng)格式轉(zhuǎn)化

35、的二進(jìn)制數(shù)據(jù)輸入輸如果要從標(biāo)準(zhǔn)輸入中讀入,或?qū)?shù)據(jù)寫至標(biāo)準(zhǔn)輸出上,則可寫成: fscanf (stdin, format , arg1, arg2, argn );和 fprintf (stdout, format , arg1, arg2, argn );為了簡(jiǎn)化書寫,對(duì)于上述兩種形式的操作,標(biāo)準(zhǔn)I/O庫還提供了同樣功能的格式輸入與輸出例行程序: scanf (format , arg1, arg2, argn );和 printf (format , arg1, arg2, argn );這就是大家都很熟悉的C語言輸入和輸出函數(shù)。43如果要從標(biāo)準(zhǔn)輸入中讀入,或?qū)?shù)據(jù)寫至標(biāo)準(zhǔn)輸出上,則可寫成

36、:45 流的單字符I/O操作(1)單字符讀寫 如果每次只要從流文件中讀入一個(gè)字符或向流文件中輸出一個(gè)字符,可使用下面兩個(gè)例行程序: c = fgetc (fp) 和 fputc (c, fp) char c; FILE *fp;445 流的單字符I/O操作(1)單字符讀寫 如果每次只要從(2)單字符標(biāo)準(zhǔn)輸入輸出要從標(biāo)準(zhǔn)輸入中讀進(jìn)一個(gè)字符,或把一個(gè)字符寫至標(biāo)準(zhǔn)輸出上,則可使用下面兩個(gè)例行程序: c = fgetc (stdin);和 fputc (c, stdout);也可寫成如下的形式: c = getc (stdin); putc (c, stdout);45(2)單字符標(biāo)準(zhǔn)輸入輸出要從標(biāo)準(zhǔn)

37、輸入中讀進(jìn)一個(gè)字符,或把一個(gè)其實(shí),getc和putc不是函數(shù),而是stdio.h定義的宏,例如:#define getc (p) (-(p)_cnt? int*(p)_ptr+ & 0377 :_filbuf (p)) #define putc (x, p) (-(p)_cnt? (int)(*(p)_ptr+ = unsigned(x) :_flushbuf(unsigned)(x), p)46其實(shí),getc和putc不是函數(shù),而是stdio.h定義的宏另外兩種更加方便的書寫形式是: c = getchar( ); putchar(c);這兩個(gè)操作同樣也是在stdio中定義的宏: #defi

38、ne getchar( ) getc(stdin) #define putchar(C) putc(c, stdout)下列兩組單字符I/O操作在功能上是相同的: c=fgetc(stdin);c=getc(stdin);c=getchar( ); 和 fputc(c,stdout);putc(c,stdout);putchar(c);由于使用了用戶態(tài)空間的緩沖,故執(zhí)行這些單字符I/O操作大大減少了對(duì)應(yīng)的系統(tǒng)調(diào)用的次數(shù),也就是減少了用戶態(tài)與核心態(tài)切換的開銷。47另外兩種更加方便的書寫形式是:47(3) 退回一個(gè)字符 ungetc可以將一個(gè)字符放回一個(gè)流中: ungetc(c, fp); cha

39、r c; FILE *fp; 在執(zhí)行過任何流的輸入操作后,只允許對(duì)每個(gè)文件退回剛讀出的一個(gè)字符,但一般只用于在單字符輸入操作之后。這個(gè)操作只是一個(gè)邏輯操作,不改變輸入文件本身。如果該操作成功,下次讀出的第一個(gè)字符就是ungetc操作放入的字符。 當(dāng)為了測(cè)試某個(gè)條件而從流文件中多讀入了一個(gè)字符后,就可用ungetc操作將該字符放回去,使流恢復(fù)成原先狀態(tài)。48(3) 退回一個(gè)字符 ungetc可以將一個(gè)字符放回一個(gè)流中6 行的輸入與輸出從流文件中讀入一行或向流文件中寫入一行: retstring = fgets(buf, size, fp); fputs(string, fp); char *bu

40、f, *retsting, *string; int size; FILE *fp;fgets從流fp中讀字符,直至讀到換行符或文件結(jié)束,但一次最多讀size個(gè)字符。讀出的字符連同換行符存入緩沖區(qū)buf中。返回指向buf的指針。fputs將一行字符串string寫入流文件fp中。496 行的輸入與輸出從流文件中讀入一行或向流文件中寫入一行:4從標(biāo)準(zhǔn)輸入上讀入一行或向標(biāo)準(zhǔn)輸出上寫一行信息: retstring = gets(buf); puts (string); char *buf, *retstring, *string;gets把從stdin中輸入的一行信息存入buf中,然后將換行符置換成

41、串結(jié)尾符NULL。用戶要保證緩沖區(qū)的長(zhǎng)度大于或等于最大的行長(zhǎng)。puts將以NULL結(jié)尾的字符串寫至標(biāo)準(zhǔn)輸出流stdout中,但串末尾的NULL字符改寫成換行符。應(yīng)當(dāng)注意前后兩組行輸入和輸出操作對(duì)換行符和NULL字符處理的差別。50從標(biāo)準(zhǔn)輸入上讀入一行或向標(biāo)準(zhǔn)輸出上寫一行信息: rets7 存儲(chǔ)區(qū)中的格式轉(zhuǎn)化下面兩個(gè)例行程序?qū)嶋H上不是有關(guān)文件或標(biāo)準(zhǔn)輸入輸出函數(shù),使用格式為: sscanf (buf, format, arg1, arg2, , argn); sprintf (buf, format , arg1, arg2, , argn); char *buf, *format;sscanf函

42、數(shù)中各個(gè)參數(shù)所需的值不是從終端或文件中輸入,而是取自緩沖區(qū)buf中。數(shù)據(jù)流方向相反的sprintf函數(shù)則將各個(gè)參數(shù)的值存入緩沖區(qū)buf中。格式說明串format則規(guī)定了數(shù)據(jù)傳送時(shí)的格式變換。517 存儲(chǔ)區(qū)中的格式轉(zhuǎn)化下面兩個(gè)例行程序?qū)嶋H上不是有關(guān)文件或標(biāo)8 程序的執(zhí)行類似于系統(tǒng)調(diào)用exec,例行程序庫向程序員提供了在一個(gè)程序中執(zhí)行另一個(gè)獨(dú)立程序的函數(shù)調(diào)用,其中最基本的是system,其格式為: retval = system (command); char *command; int retval;例如:system (ls -l);例行程序庫在實(shí)現(xiàn)system函數(shù)時(shí),先創(chuàng)建一個(gè)子進(jìn)程,然后讓

43、子進(jìn)程改換自己的圖像,裝入并執(zhí)行標(biāo)準(zhǔn)shell (/bin/sh),并由shell 執(zhí)行參數(shù)所指定的命令。故system例行程序執(zhí)行完畢就返回至主調(diào)程序,而不是像exec調(diào)用,正常執(zhí)行后不會(huì)返回到主調(diào)程序。528 程序的執(zhí)行類似于系統(tǒng)調(diào)用exec,例行程序庫向程序員提供6.6 UNIX文件系統(tǒng)的內(nèi)部結(jié)構(gòu)6.6.1 索引節(jié)點(diǎn)(Index Node)文件所有的控制信息構(gòu)成了文件的索引節(jié)點(diǎn),所有的I節(jié)點(diǎn)是集中存放在磁盤上的I節(jié)點(diǎn)區(qū),故又稱為磁盤I節(jié)點(diǎn)。struct dinode ushort di_mode; 文件控制模式 short di_nlink; 文件的鏈接數(shù) ushort di_uid;

44、文件主用戶標(biāo)識(shí)數(shù) ushort di_gid; 文件主同組用戶組標(biāo)識(shí)數(shù) off_t di_size; 文件長(zhǎng)度,以字節(jié)為單位 char di_addr40; 地址索引表,存放文件的盤塊號(hào) time_t di_atime; 文件最近一次訪問時(shí)間 time_t di_mtime; 文件最近一次修改時(shí)間 time_t di_ctime; 文件創(chuàng)建時(shí)間536.6 UNIX文件系統(tǒng)的內(nèi)部結(jié)構(gòu)6.6.1 索引節(jié)點(diǎn)(In在結(jié)構(gòu)成員中,di_mode的各個(gè)二進(jìn)制位或它們的組合分別定義了文件的類型、執(zhí)行時(shí)置文件主或組用戶標(biāo)識(shí)符、常駐盤交換區(qū)和文件的存取控制數(shù)。ls -l命令列出的第一字段的內(nèi)容就是取自本結(jié)構(gòu)的這

45、個(gè)成員。字符數(shù)組di_addr40中每三個(gè)字節(jié)組成一個(gè)單元,以記錄文件的盤塊號(hào),構(gòu)成了13個(gè)表項(xiàng)的地址索引表,將其設(shè)置成40字節(jié)大小是為了使索引節(jié)點(diǎn)的大小為64字節(jié),以便在一個(gè)盤塊中正好放滿整數(shù)個(gè)(對(duì)1K大小的盤塊,可放16個(gè))I節(jié)點(diǎn)。54在結(jié)構(gòu)成員中,di_mode的各個(gè)二進(jìn)制位或它們的組合分別定6.6.2 文件索引結(jié)構(gòu)UNIX將這13個(gè)表項(xiàng)分成四種尋址方式。(1) 直接尋址據(jù)統(tǒng)計(jì),UNIX系統(tǒng)中文件大小在8KB以下的占85%,為了提高對(duì)絕大多數(shù)文件的訪問速度,宜采用直接尋址方式。為此,地址索引表中的前10個(gè)表項(xiàng)直接存放文件前10個(gè)邏輯塊的物理盤塊地址。556.6.2 文件索引結(jié)構(gòu)UNIX將

46、這13個(gè)表項(xiàng)分成四種尋址方(2) 一級(jí)間接尋址對(duì)于長(zhǎng)度大于10個(gè)盤塊的文件,其前10個(gè)盤塊還是采用直接尋址方式,后面的盤塊部分采用一級(jí)間接尋址方式。也即在地址索引表的第11個(gè)表項(xiàng)登記的不是文件的物理盤塊號(hào),而是一個(gè)索引塊的地址。每個(gè)表項(xiàng)存放文件第10個(gè)邏輯塊以后的物理盤塊的地址采用這種索引方式的文件大小為1024/3=341KB,與直尋址方式相加,文件最大長(zhǎng)度為351KB。56(2) 一級(jí)間接尋址對(duì)于長(zhǎng)度大于10個(gè)盤塊的文件,其前10個(gè)(3) 二級(jí)間接尋址對(duì)于長(zhǎng)度超過前二種尋址方式所能尋址的文件,超過部分則采用二級(jí)間接尋址方式。在地址索引表的第12個(gè)表項(xiàng)中登記了一個(gè)具有341個(gè)表項(xiàng)的間接索引塊

47、地址,間接索引塊的每一個(gè)表項(xiàng)又各登記了一個(gè)具有341個(gè)表項(xiàng)的索引塊地址,在這級(jí)索引塊中的表項(xiàng)才有存放文件的物理盤塊地址。單用二級(jí)間接索引就可訪問341341個(gè)文件物理塊。57(3) 二級(jí)間接尋址對(duì)于長(zhǎng)度超過前二種尋址方式所能尋址的文件(4) 三級(jí)間接尋址對(duì)于長(zhǎng)度超過前三種尋址方式所能尋址的文件,超過部分采用三級(jí)間接索引,其尋址原理與上類似。單用三級(jí)間接尋址方式所能訪問的物理盤塊數(shù)為341341341塊。如此,UNIX的文件索引結(jié)構(gòu)如圖6-4所示,文件的尋址方式是隨著文件長(zhǎng)度的擴(kuò)充逐步升級(jí)的。以上四種尋址方式所能訪問的文件最大長(zhǎng)度為(10+341+341341+341341341)KB,即近40

48、G。文件的長(zhǎng)度還要受I節(jié)點(diǎn)中記錄文件長(zhǎng)度的成員di_size的取值限制,di_size為32位的無符號(hào)長(zhǎng)整型,這樣文件的最大長(zhǎng)度為232 byte = 4G。58(4) 三級(jí)間接尋址對(duì)于長(zhǎng)度超過前三種尋址方式所能尋址的文件圖6-4 UNIX文件索引結(jié)構(gòu)一級(jí)間接塊直接尋址塊直接尋址塊一級(jí)間接塊二級(jí)間接塊直接尋址塊addr 一級(jí)間接二級(jí)間接三級(jí)間接直接尋址01211109159圖6-4 UNIX文件索引結(jié)構(gòu)一級(jí)間接塊直接尋址塊直接尋址6.6.3 目錄結(jié)構(gòu)1. 目錄項(xiàng)結(jié)構(gòu) 每個(gè)目錄項(xiàng)由1個(gè)2字節(jié)的I節(jié)點(diǎn)號(hào)和 14字節(jié)的文件名分量組成,現(xiàn)在UNIX系統(tǒng)的文件名分量可擴(kuò)展。 struct direct

49、ino_t d_ino; /* 對(duì)應(yīng)文件的I節(jié)點(diǎn) */ char d_name 14;/* 文件名 */I節(jié)點(diǎn)號(hào)di_node文件名圖6-5 目錄項(xiàng)與I節(jié)點(diǎn)d_inodi_name 606.6.3 目錄結(jié)構(gòu)1. 目錄項(xiàng)結(jié)構(gòu) 每個(gè)目錄項(xiàng)由1個(gè)22. 目錄結(jié)構(gòu) UNIX將同一目錄下的所有文件的目錄項(xiàng)數(shù)據(jù)組成一個(gè)目錄文件,一個(gè)目錄文件可由一至多盤塊組成。 目錄文件中的前二個(gè)目錄項(xiàng)的文件名比較特殊,它們?yōu)椤?”和“. ”,分別表示當(dāng)前目錄和父目錄,它們的I節(jié)點(diǎn)號(hào)就是當(dāng)前目錄文件的I節(jié)點(diǎn)號(hào)和上一級(jí)目錄文件的I節(jié)點(diǎn)號(hào),這便于用戶在目錄系統(tǒng)中移動(dòng)位置。612. 目錄結(jié)構(gòu) UNIX將同一目錄下的所有文件的目錄

50、項(xiàng)數(shù)據(jù)組根目錄文件的I節(jié)點(diǎn)是存放在磁盤I節(jié)點(diǎn)區(qū)的固定位置上(由全局變量rootdir指示),故根目錄文件不需要有目錄項(xiàng),它是無名的。從根開始,根目錄的下級(jí)目錄的名字存放在根目錄文件的目錄項(xiàng)中,并各有一個(gè)指針指示下級(jí)目錄文件的I節(jié)點(diǎn)。如此一級(jí)一級(jí)擴(kuò)展下去,直至最底層的數(shù)據(jù)文件或空的目錄文件,構(gòu)成了整個(gè)UNIX的樹型目錄結(jié)構(gòu)。62根目錄文件的I節(jié)點(diǎn)是存放在磁盤I節(jié)點(diǎn)區(qū)的固定位置上(由全局變I節(jié)點(diǎn)目錄文件塊目錄項(xiàng)n目錄項(xiàng)1文件物理盤塊圖6-6 UNIX目錄系統(tǒng)結(jié)構(gòu)di_addr di_addr 目錄項(xiàng)目錄項(xiàng)根目錄文件塊目錄項(xiàng)n目錄項(xiàng)1根目錄文件I節(jié)點(diǎn)di_addr I節(jié)點(diǎn)di_addr di_add

51、r 63I節(jié)點(diǎn)目錄目錄項(xiàng)n目錄項(xiàng)1文件物理盤塊圖6-6 UNIX目3目錄中的勾連在UNIX同一個(gè)文件系統(tǒng)中,同一層次或不同層次的目錄項(xiàng)可指向同一個(gè)文件的I節(jié)點(diǎn),這就是目錄結(jié)構(gòu)的勾連。目錄的勾連可由系統(tǒng)調(diào)用link 建立,不同用戶可以在不同的位置上用不同的文件名訪問同一個(gè)文件。這為文件的共享提供了方便,這也是UNIX為什么要將文件的目錄項(xiàng)與I節(jié)點(diǎn)分開存儲(chǔ)和管理的主要原因之一。643目錄中的勾連在UNIX同一個(gè)文件系統(tǒng)中,同一層次或不同層4目錄搜索有兩種路徑名,絕對(duì)路徑名和相對(duì)路徑名。對(duì)于絕對(duì)路徑名,如/etc/passwd,系統(tǒng)先得到根I節(jié)點(diǎn),再根據(jù)其中的地址索引表將根目錄文件的盤塊內(nèi)容讀入內(nèi)存

52、,并逐項(xiàng)比較,看其中是否有一個(gè)目錄項(xiàng)的文件名與根的下一層路徑名分量,如etc相匹配。找到匹配項(xiàng)后,根據(jù)該項(xiàng)的I節(jié)點(diǎn)號(hào)再得到下層目錄文件的I節(jié)點(diǎn)。通過該I節(jié)點(diǎn)的地址索引表,讀入etc目錄文件的物理盤塊。在該盤塊中再逐項(xiàng)比較,直至找到文件名為passwd的目錄項(xiàng)并獲得passwd文件的I節(jié)點(diǎn)和讀取passwd文件的各個(gè)物理盤塊內(nèi)容。如用戶給出的是相對(duì)路徑名,則除了起始搜索點(diǎn)是當(dāng)前目錄項(xiàng)的I節(jié)點(diǎn)外,其余并無不同之處。654目錄搜索有兩種路徑名,絕對(duì)路徑名和相對(duì)路徑名。656.6.4 打開文件結(jié)構(gòu)訪問一個(gè)文件時(shí),系統(tǒng)要從根目錄或當(dāng)前目錄出發(fā),循序讀取和搜索各級(jí)目錄文件磁盤I節(jié)點(diǎn),索引結(jié)構(gòu)等,找到文件物

53、理塊號(hào)后再存取文件數(shù)據(jù)。由于文件系統(tǒng)十分龐大,這個(gè)操作比較費(fèi)時(shí)。要訪問一個(gè)文件,最關(guān)鍵的是要取得該文件的I節(jié)點(diǎn),由它可進(jìn)一步獲得文件的所有控制信息及數(shù)據(jù)塊。為了提高打開文件后對(duì)文件訪問速度,當(dāng)讀取該文件的I節(jié)點(diǎn)后,應(yīng)當(dāng)在對(duì)整個(gè)文件的訪問期間內(nèi),在內(nèi)存中保存該I節(jié)點(diǎn)的副本,并能通過一個(gè)方便快速的途徑存取它,這就要建立打開文件管理機(jī)構(gòu)。打開文件的管理機(jī)構(gòu)包括三部分,它們是內(nèi)存索引節(jié)點(diǎn)、系統(tǒng)打開文件控制塊和進(jìn)程打開文件表。666.6.4 打開文件結(jié)構(gòu)訪問一個(gè)文件時(shí),系統(tǒng)要從根目錄或當(dāng)前1. 內(nèi)存索引節(jié)點(diǎn) struct inode struct inod *i_forw; 內(nèi)存I節(jié)點(diǎn)的散列隊(duì)列雙向循環(huán)

54、勾連指針 struct inod *i_back; char i_flag; 狀態(tài)標(biāo)志,如鎖標(biāo)志、修改標(biāo)志等 cnt_t i_count; 引用計(jì)數(shù),表示該文件打開了幾次 dev_t i_dev; 文件所在的設(shè)備號(hào) ino_t i_number; 對(duì)應(yīng)的磁盤索引節(jié)點(diǎn)號(hào) struct union daddr_t i_a13; 常規(guī)文件或目錄文件的地址索引表 short i_f26 管道文件的地址索引表 i_p; daddr_t i_l 最近一次讀入的文件邏輯塊,用于預(yù)讀 i_blk;671. 內(nèi)存索引節(jié)點(diǎn) struct inode 67磁盤I節(jié)點(diǎn)某些信息在文件打開的期間是不需訪問和處理的,例如文

55、件的最近訪問、修改的時(shí)間等,要等關(guān)閉文件時(shí),才根據(jù)當(dāng)前的時(shí)間重新更新對(duì)應(yīng)的記錄項(xiàng)。另一方面,為了便于檢索內(nèi)存I節(jié)點(diǎn)和在關(guān)閉時(shí)將I節(jié)點(diǎn)寫入磁盤原先的位置,又要增加一部分信息。68磁盤I節(jié)點(diǎn)某些信息在文件打開的期間是不需訪問和處理的,例如文2.打開文件控制塊 一個(gè)文件可以被不同進(jìn)程以不同的操作要求同時(shí)打開,而且對(duì)文件操作的當(dāng)前指針也不同。 struct file char f_flag; 操作方式,如寫、讀、追加寫等 cnt_t f_count; 共享該file結(jié)構(gòu)的進(jìn)程數(shù) union struct inode *f_uinode; 指向內(nèi)存I節(jié)點(diǎn) struct file *f_unext; 空閑

56、file的鏈接指針 f_up; union off_t f_off; 讀寫位置指針 f_un;692.打開文件控制塊 一個(gè)文件可以被不同進(jìn)程以不同的操作要求同3進(jìn)程打開文件表進(jìn)程打開文件表或稱打開文件描述字表是進(jìn)程擴(kuò)充控制塊user結(jié)構(gòu)中一個(gè)指針數(shù)組struct file *u_ofileNOFILE。進(jìn)程在打開文件時(shí)按下標(biāo)序由低至高順次使用該數(shù)組中的某一空閑項(xiàng),在該表項(xiàng)中填入打開文件控制塊file結(jié)構(gòu)變量的地址,打開文件描述字的值就是該空閑項(xiàng)的下標(biāo)值。程序以打開文件描述字fd的值,索引指針數(shù)組u_ofile,從對(duì)應(yīng)的表項(xiàng)中可獲得打開文件控制塊地址,進(jìn)一步可得到內(nèi)存I節(jié)點(diǎn)的文件的控制信息及數(shù)據(jù)

57、塊。703進(jìn)程打開文件表進(jìn)程打開文件表或稱打開文件描述字表是進(jìn)程擴(kuò)file inode文件塊u_ofile fd:f_uinodei_a 13圖6-7 打開文件機(jī)構(gòu)進(jìn)程打開一個(gè)文件時(shí),系統(tǒng)要為其分配一個(gè)空閑內(nèi)存inode,將磁盤I節(jié)點(diǎn)的主要內(nèi)容復(fù)制到其中。接著再分配一個(gè)空閑打開文件控制結(jié)構(gòu)file,并使f_ninode指針指向內(nèi)存inode 。最后再在進(jìn)程user結(jié)構(gòu)的u_ofile中找到一個(gè)空閑項(xiàng),在其中記下file結(jié)構(gòu)的地址,并使數(shù)組索引值作為打開文件描述字返回給用戶。71file inode文件塊u_ofile fd:34Pb34Pc進(jìn)程34Pau_ofilefile內(nèi)存inodef_u

58、inodef_count:2f_uinodef_count:1f_uinodef_count:1f_uinodef_count:1f_uinodef_count:1i_count:2i_count:2i_count:1圖6-8 繼承和獨(dú)立打開文件結(jié)構(gòu) WRONLYWRONLYRDONLYRDONLY RDWR7234Pb34Pc進(jìn)程34Pau_ofilefile內(nèi)存ino圖6-8表示了不同共享方式打開文件結(jié)構(gòu)的各部分之間聯(lián)系。進(jìn)程Pa以寫方式打開了3#文件后建立了u_ofile到file及file到內(nèi)存inode的聯(lián)系路徑,此時(shí)file結(jié)構(gòu)中的f_count值及inode結(jié)構(gòu)中的i_count

59、的值都為1。此后,進(jìn)程Pa創(chuàng)建了子進(jìn)程Pb,子進(jìn)程Pb user結(jié)構(gòu)的u_ofile的值與其父進(jìn)程完全相同,故共享父進(jìn)程Pa的所有打開文件,包括0#,1#,2#和3#文件。對(duì)于3#文件,子進(jìn)程Pb與父進(jìn)程Pa指向同一個(gè)file結(jié)構(gòu),故子進(jìn)程對(duì)共享文件的操作方式也與父進(jìn)程相同,不過file結(jié)構(gòu)中的f_count的值變成了2,表示有兩個(gè)進(jìn)程打開文件的表項(xiàng)聯(lián)系了同一file,但此時(shí)內(nèi)存inode結(jié)構(gòu)中的i_count值還是1。73圖6-8表示了不同共享方式打開文件結(jié)構(gòu)的各部分之間聯(lián)系。進(jìn)程父進(jìn)程在創(chuàng)建了子進(jìn)程后,又以不同方式(只讀方式)打開原先已打開的文件。系統(tǒng)將為其新分配一個(gè)file結(jié)構(gòu),使fil

60、e結(jié)構(gòu)中的f_uinode指向同一個(gè)內(nèi)存inode(此時(shí)內(nèi)存inode的i_count值變成2),并在進(jìn)程打開文件表中下一可用項(xiàng)指向該file結(jié)構(gòu)。此后,子進(jìn)程Pb也獨(dú)立打開了另一個(gè)文件,建立了u_ofile到該文件內(nèi)存inode的聯(lián)系。另一個(gè)獨(dú)立的進(jìn)程Pc則打開了進(jìn)程Pb已打開的文件,且又獨(dú)自打開了另一個(gè)文件,此時(shí)打開文件結(jié)構(gòu)的情形及f_count和i_count的值如圖6-8所示。74父進(jìn)程在創(chuàng)建了子進(jìn)程后,又以不同方式(只讀方式)打開原先已打6.6.5 文件系統(tǒng)存儲(chǔ)資源管理1.文件系統(tǒng)存儲(chǔ)機(jī)構(gòu)的總體安排一個(gè)文件系統(tǒng)(或稱文件卷)對(duì)應(yīng)與一臺(tái)邏輯設(shè)備。現(xiàn)在磁盤容量很大,一個(gè)物理磁盤可以劃分成

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論