昨晚上女友問我,你知道啥是文件嗎?于是就有了今天的文章
所有的應(yīng)用程序都需要存儲(chǔ)和檢索信息。當(dāng)進(jìn)程運(yùn)行時(shí),它能夠在自己的存儲(chǔ)空間內(nèi)存儲(chǔ)一定量的信息。然而,存儲(chǔ)容量受虛擬地址空間大小的限制。對(duì)于一些應(yīng)用程序來說,存儲(chǔ)空間的大小是充足的,但是對(duì)于其他一些應(yīng)用程序,比如航空訂票系統(tǒng)、銀行系統(tǒng)、企業(yè)記賬系統(tǒng)來說,這些容量又顯得太小了。
在進(jìn)程的地址空間上保存信息的第二個(gè)問題是,當(dāng)進(jìn)程終止時(shí)信息會(huì)丟失。對(duì)于一些應(yīng)用程序(例如數(shù)據(jù)庫(kù)),信息會(huì)長(zhǎng)久保留。在這些進(jìn)程終止時(shí),相關(guān)的信息應(yīng)該保留下來,是不能夠丟失的。甚至是,即便這些應(yīng)用程序崩潰后,這些信息也應(yīng)該保留下來。
第三個(gè)問題是,通常需要很多進(jìn)程在同一時(shí)刻訪問這些信息。解決這種問題的方式是把這些信息單獨(dú)保留在各自的進(jìn)程中。
因此,對(duì)于長(zhǎng)久存儲(chǔ)的信息我們有三個(gè)基本需求:
- 必須要有可能存儲(chǔ)的大量的信息
- 信息必須能夠在進(jìn)程終止時(shí)保留
- 必須能夠使多個(gè)進(jìn)程同時(shí)訪問有關(guān)信息
磁盤(Magnetic disk) 一直是用來長(zhǎng)久保存信息的設(shè)備。近些年來,固態(tài)硬盤逐漸流行起來。
固態(tài)硬盤不僅沒有易損壞的移動(dòng)部件,而且能夠提供快速的隨機(jī)訪問。相比而言,雖然磁帶和光盤也被廣泛使用,但是它們的性能相對(duì)較差,通常應(yīng)用于備份。我們會(huì)在后面探討磁盤,現(xiàn)在姑且把磁盤當(dāng)作一種大小固定塊的線性序列好了,并且支持如下操作:
- 讀塊 k
- 寫塊 k
事實(shí)上磁盤支持更多的操作,但是只要有了讀寫操作,原則上就能夠解決長(zhǎng)期存儲(chǔ)的問題。
然而,磁盤還有一些不便于實(shí)現(xiàn)的操作,特別是在有很多程序或者多用戶使用著的大型系統(tǒng)上(如服務(wù)器)。在這種情況下,很容易產(chǎn)生一些問題,例如:
- 你如何找到這些信息?
- 你如何保證一個(gè)用戶不會(huì)讀取另外一個(gè)用戶的數(shù)據(jù)?
- 你怎么知道哪些塊是空閑的?
還有一些其他更多的問題。
我們可以針對(duì)這些問題提出一個(gè)新的抽象 - 文件。進(jìn)程和線程的抽象、地址空間和文件都是操作系統(tǒng)的重要概念。如果你能真正深入了解這三個(gè)概念,那么你就走上了成為操作系統(tǒng)專家的道路。
文件(Files)是由進(jìn)程創(chuàng)建的邏輯信息單元。一個(gè)磁盤會(huì)包含幾千甚至幾百萬個(gè)文件,每個(gè)文件是獨(dú)立于其他文件的。事實(shí)上,如果你能把每個(gè)文件都看作一個(gè)獨(dú)立的地址空間,那么你就可以真正理解文件的概念了。
進(jìn)程能夠讀取已經(jīng)存在的文件,并在需要時(shí)重新創(chuàng)建他們。存儲(chǔ)在文件中的信息必須是持久的,這也就是說,不會(huì)因?yàn)檫M(jìn)程的創(chuàng)建和終止而受影響。一個(gè)文件只能在當(dāng)用戶明確刪除的時(shí)候才能消失。盡管讀取和寫入都是最基本的操作,但還有許多其他操作,我們將在下面介紹其中的一些。
文件由操作系統(tǒng)進(jìn)行管理,有關(guān)文件的構(gòu)造、命名、訪問、使用、保護(hù)、實(shí)現(xiàn)和管理方式都是操作系統(tǒng)設(shè)計(jì)的主要內(nèi)容。從總體上看,操作系統(tǒng)中處理文件的部分稱為 文件系統(tǒng)(file system),這就是我們所討論的。
從用戶角度來說,用戶通常會(huì)關(guān)心文件是由什么組成的,如何給文件進(jìn)行命名,如何保護(hù)文件,以及可以對(duì)文件進(jìn)行哪些操作等等。盡管是用鏈表還是用位圖記錄內(nèi)存空閑區(qū)并不是用戶所關(guān)心的主題,而這些對(duì)系統(tǒng)設(shè)計(jì)人員來說至關(guān)重要。下面我們就來探討一下這些主題。
文件
1. 文件命名
文件是一種抽象機(jī)制,它提供了一種方式用來存儲(chǔ)信息以及在后面進(jìn)行讀取。可能任何一種機(jī)制最重要的特性就是管理對(duì)象的命名方式。在創(chuàng)建一個(gè)文件后,它會(huì)給文件一個(gè)命名。當(dāng)進(jìn)程終止時(shí),文件會(huì)繼續(xù)存在,并且其他進(jìn)程可以使用名稱訪問該文件。
文件命名規(guī)則對(duì)于不同的操作系統(tǒng)來說是不一樣的,但是所有現(xiàn)代操作系統(tǒng)都允許使用 1 - 8 個(gè)字母的字符串作為合法文件名。
某些文件區(qū)分大小寫字母,而大多數(shù)則不區(qū)分。UNIX 屬于第一類;歷史悠久的 MS-DOS 屬于第二類(順便說一句,盡管 MS-DOS 歷史悠久,但 MS-DOS 仍在嵌入式系統(tǒng)中非常廣泛地使用,因此它絕不是過時(shí)的);因此,UNIX 系統(tǒng)會(huì)有三種不同的命名文件:maria、Maria、MARIA 。在 MS-DOS ,所有這些命名都屬于相同的文件。
這里可能需要在文件系統(tǒng)上預(yù)留一個(gè)位置。Windows 95 和 Windows 98 都使用了 MS-DOS 文件系統(tǒng),叫做 FAT-16,因此繼承了它的一些特征,例如有關(guān)文件名的構(gòu)造方法。Windows 98 引入了對(duì) FAT-16 的一些擴(kuò)展,從而導(dǎo)致了 FAT-32 的生成,但是這兩者很相似。另外,Windows NT,Windows 2000,Windows XP,Windows Vista,Windows 7 和 Windows 8 都支持 FAT 文件系統(tǒng),這種文件系統(tǒng)有些過時(shí)。然而,這些較新的操作系統(tǒng)還具有更高級(jí)的本機(jī)文件系統(tǒng)(NTFS),有不同的特性,那就是基于 Unicode 編碼的文件名。事實(shí)上,Windows 8 還配備了另一種文件系統(tǒng),簡(jiǎn)稱 ReFS(Resilient File System),但這個(gè)文件系統(tǒng)一般應(yīng)用于 Windows 8 的服務(wù)器版本。下面除非我們特殊聲明,否則我們?cè)谔岬?MS-DOS 和 FAT 文件系統(tǒng)的時(shí)候,所指的就是 Windows 的 FAT-16 和 FAT-32。這里要說一下,有一種類似 FAT 的新型文件系統(tǒng),叫做 exFAT。它是微軟公司對(duì)閃存和大文件系統(tǒng)開發(fā)的一種優(yōu)化的 FAT 32 擴(kuò)展版本。ExFAT 是現(xiàn)在微軟唯一能夠滿足 OS X讀寫操作的文件系統(tǒng)。
許多操作系統(tǒng)支持兩部分的文件名,它們之間用 . 分隔開,比如文件名 prog.c。原點(diǎn)后面的文件稱為 文件擴(kuò)展名(file extension) ,文件擴(kuò)展名通常表示文件的一些信息。例如在 MS-DOS 中,文件名是 1 - 8 個(gè)字符,加上 1 - 3 個(gè)字符的可選擴(kuò)展名組成。在 UNIX 中,如果有擴(kuò)展名,那么擴(kuò)展名的長(zhǎng)度將由用戶來決定,一個(gè)文件甚至可以包括兩個(gè)或更多的擴(kuò)展名,例如 homepage.html.zip,html 表示一個(gè) web 網(wǎng)頁(yè)而 .zip 表示文件homepage.html 已經(jīng)采用 zip 程序壓縮完成。一些常用的文件擴(kuò)展名以及含義如下圖所示:
在 UNIX 系統(tǒng)中,文件擴(kuò)展名只是一種約定,操作系統(tǒng)并不強(qiáng)制采用。
名為 file.txt 的文件是文本文件,這個(gè)文件名更多的是提醒所有者,而不是給計(jì)算機(jī)傳遞信息。但是另一方面,C 編譯器可能要求它編譯的文件以.c 結(jié)尾,否則它會(huì)拒絕編譯。然而,操作系統(tǒng)并不關(guān)心這一點(diǎn)。
對(duì)于可以處理多種類型的程序,約定就顯得及其有用。例如 C 編譯器可以編譯、鏈接多種文件,包括 C 文件和匯編語(yǔ)言文件。這時(shí)擴(kuò)展名就很有必要,編譯器利用它們區(qū)分哪些是 C 文件,哪些是匯編文件,哪些是其他文件。因此,擴(kuò)展名對(duì)于編譯器判斷哪些是 C 文件,哪些是匯編文件以及哪些是其他文件變得至關(guān)重要。
與 UNIX 相反,Windows 就會(huì)關(guān)注擴(kuò)展名并對(duì)擴(kuò)展名賦予了新的含義。用戶(或進(jìn)程) 可以在操作系統(tǒng)中注冊(cè)擴(kuò)展名,并且規(guī)定哪個(gè)程序能夠擁有擴(kuò)展名。當(dāng)用戶雙擊某個(gè)文件名時(shí),擁有該文件名的程序就啟動(dòng)并運(yùn)行文件。例如,雙擊 file.docx 啟動(dòng)了 Word 程序,并以 file.docx 作為初始文件。
2. 文件結(jié)構(gòu)
文件的構(gòu)造有多種方式。下圖列出了常用的三種構(gòu)造方式:
上圖中的 a 是一種無結(jié)構(gòu)的字節(jié)序列,操作系統(tǒng)不關(guān)心序列的內(nèi)容是什么,操作系統(tǒng)能看到的就是字節(jié)(bytes)。其文件內(nèi)容的任何含義只在用戶程序中進(jìn)行解釋。UNIX 和 Windows 都采用這種辦法。
把文件看成字節(jié)序列提供了最大的靈活性。用戶程序可以向文件中寫任何內(nèi)容,并且可以通過任何方便的形式命名。操作系統(tǒng)不會(huì)為為用戶寫入內(nèi)容提供幫助,當(dāng)然也不會(huì)干擾阻塞你。對(duì)于想做特殊操作的用戶來說,后者是十分重要的。所有的 UNIX 版本(包括 Linux 和 OS X)和 Windows 都使用這種文件模型。
圖 b 表示在文件結(jié)構(gòu)上的第一步改進(jìn)。在這個(gè)模型中,文件是具有固定長(zhǎng)度記錄的序列,每個(gè)記錄都有其內(nèi)部結(jié)構(gòu)。把文件作為記錄序列的核心思想是:讀操作返回一個(gè)記錄,而寫操作重寫或者追加一個(gè)記錄。第三種文件結(jié)構(gòu)如上圖 c 所示。在這種組織結(jié)構(gòu)中,文件由一顆記錄樹構(gòu)成,記錄樹的長(zhǎng)度不一定相同,每個(gè)記錄樹都在記錄中的固定位置包含一個(gè)key字段。這棵樹按 key 進(jìn)行排序,從而可以對(duì)特定的 key 進(jìn)行快速查找。
在記錄樹的結(jié)構(gòu)中,可以取出下一個(gè)記錄,但是最關(guān)鍵的還是根據(jù) key 搜索指定的記錄。如上圖 c 所示,用戶可以讀出指定的 pony 記錄,而不必關(guān)心記錄在文件中的確切位置。用戶也可以在文件中添加新的記錄。但是用戶不能決定添加到何處位置,添加到何處位置是由操作系統(tǒng)決定的。
3. 文件類型
很多操作系統(tǒng)支持多種文件類型。例如,UNIX(同樣包括 OS X)和 Windows 都具有常規(guī)的文件和目錄。除此之外,UNIX 還具有字符特殊文件(character special file) 和 塊特殊文件(block special file)。常規(guī)文件(Regular files) 是包含有用戶信息的文件。用戶一般使用的文件大都是常規(guī)文件,常規(guī)文件一般包括 可執(zhí)行文件、文本文件、圖像文件,從常規(guī)文件讀取數(shù)據(jù)或?qū)?shù)據(jù)寫入時(shí),內(nèi)核會(huì)根據(jù)文件系統(tǒng)的規(guī)則執(zhí)行操作,寫入可能被延遲,記錄日志或者接受其他操作。
字符特殊文件和輸入/輸出有關(guān),用于串行 I/O 類設(shè)備,如終端、打印機(jī)、網(wǎng)絡(luò)等。塊特殊文件用于磁盤類設(shè)備。我們主要討論的是常規(guī)文件。
常規(guī)文件一般分為 ASCII 碼文件或者二進(jìn)制文件。ASCII 碼文件由文本組成。在一些系統(tǒng)中,每行都會(huì)用回車符結(jié)束(ASCII碼是13,控制字符 CR,轉(zhuǎn)義字符\r。),另外一些則會(huì)使用換行符(ASCII碼是10,控制字符LF,轉(zhuǎn)義字符\n)。一些系統(tǒng)(比如 Windows)兩者都會(huì)使用。
ASCII 文件的優(yōu)點(diǎn)在于顯示 和 打印,還可以用任何文本編輯器進(jìn)行編輯。進(jìn)一步來說,如果許多應(yīng)用程序使用 ASCII 碼作為輸入和輸出,那么很容易就能夠把多個(gè)程序連接起來,一個(gè)程序的輸出可能是另一個(gè)程序的輸入,就像管道一樣。
其他與 ASCII 不同的是二進(jìn)制文件。打印出來的二進(jìn)制文件是無法理解的。下面是一個(gè)二進(jìn)制文件的格式,它取自早期的 UNIX 。盡管從技術(shù)上來看這個(gè)文件只是字節(jié)序列,但是操作系統(tǒng)只有在文件格式正確的情況下才會(huì)執(zhí)行。
這個(gè)文件有五個(gè)段:文件頭、正文、數(shù)據(jù)、重定位位和符號(hào)表。文件頭以 魔數(shù)(magic number) 為開始,表明這個(gè)文件是一個(gè)可執(zhí)行文件(以防止意外執(zhí)行非此格式的文件)。然后是文件各個(gè)部分的大小,開始執(zhí)行的標(biāo)志以及一些標(biāo)志位。程序本身的正文和數(shù)據(jù)在文件頭后面,他們被加載到內(nèi)存中或者重定位會(huì)根據(jù)重定位位進(jìn)行判斷。符號(hào)表則用于調(diào)試。
二進(jìn)制文件的另外一種形式是存檔文件,它由已編譯但沒有鏈接的庫(kù)過程(模塊)組合而成。每個(gè)文件都以模塊頭開始,其中記錄了名稱、創(chuàng)建日期、所有者、保護(hù)碼和文件大小。和可執(zhí)行文件一樣,模塊頭也都是二進(jìn)制數(shù),將它們復(fù)制到打印機(jī)將會(huì)產(chǎn)生亂碼。
所有的操作系統(tǒng)必須至少能夠識(shí)別一種文件類型:它自己的可執(zhí)行文件。以前的 TOPS-20 系統(tǒng)(用于DECsystem 20)甚至要檢查要執(zhí)行的任何文件的創(chuàng)建時(shí)間,為了定位資源文件來檢查自動(dòng)文件創(chuàng)建后是否被修改過。如果被修改過了,那么就會(huì)自動(dòng)編譯文件。在 UNIX 中,就是在 shell 中嵌入 make 程序。此時(shí)操作系統(tǒng)要求用戶必須采用固定的文件擴(kuò)展名,從而確定哪個(gè)源程序生成哪個(gè)二進(jìn)制文件。
什么是 make 程序?在軟件發(fā)展過程中,make 程序是一個(gè)自動(dòng)編譯的工具,它通過讀取稱為 Makefiles 的文件來自動(dòng)從源代碼構(gòu)建可執(zhí)行程序和庫(kù),該文件指定了如何導(dǎo)出目標(biāo)程序。盡管集成開發(fā)環(huán)境和特定語(yǔ)言的編譯器功能也可以用于管理構(gòu)建過程,但 Make 仍被廣泛使用,尤其是在 Unix 和類似 Unix 的操作系統(tǒng)中使用。 |
當(dāng)程序從文件中讀寫數(shù)據(jù)時(shí),請(qǐng)求會(huì)轉(zhuǎn)到內(nèi)核處理程序(kernel driver)。如果文件是常規(guī)文件,則數(shù)據(jù)由文件系統(tǒng)驅(qū)動(dòng)程序處理,并且通常存儲(chǔ)在磁盤或其他存儲(chǔ)介質(zhì)上的某塊區(qū)域中,從文件中讀取的數(shù)據(jù)就是之前在該位置寫入的數(shù)據(jù)。
當(dāng)數(shù)據(jù)讀取或?qū)懭氲皆O(shè)備文件時(shí),請(qǐng)求會(huì)被設(shè)備驅(qū)動(dòng)程序處理。每個(gè)設(shè)備文件都有一個(gè)關(guān)聯(lián)的編號(hào),該編號(hào)標(biāo)示要使用的設(shè)備驅(qū)動(dòng)程序。設(shè)備處理數(shù)據(jù)的工作是它自己的事兒。
- 塊設(shè)備 也叫做塊特殊文件,它的行為通常與普通文件相似:它們是字節(jié)數(shù)組,并且在給定位置讀取的值是最后寫入該位置的值。來自塊設(shè)備的數(shù)據(jù)可以緩存在內(nèi)存中,并從緩存中讀取;寫入可以被緩沖。塊設(shè)備通常是可搜索的,塊設(shè)備的概念是,相應(yīng)的硬件可以一次讀取或者寫入整個(gè)塊,例如磁盤上的一個(gè)扇區(qū)。
- 字符設(shè)備 也稱為字符特殊文件,它的行為類似于管道、串行端口。將字節(jié)寫入字符設(shè)備可能會(huì)導(dǎo)致它在屏幕上顯示,在串行端口上輸出,轉(zhuǎn)換為聲音。
目錄(Directories) 是管理文件系統(tǒng)結(jié)構(gòu)的系統(tǒng)文件。它是用于在計(jì)算機(jī)上存儲(chǔ)文件的位置。目錄位于分層文件系統(tǒng)中,例如 Linux,MS-DOS 和 UNIX。
它顯示所有本地和子目錄(例如,cdn 目錄中的 big 目錄)。當(dāng)前目錄是 C 盤驅(qū)動(dòng)器的根目錄。之所以稱為根目錄,是因?yàn)樵撃夸浵聸]有任何內(nèi)容,而其他目錄都在該目錄下分支。
4. 文件訪問
早期的操作系統(tǒng)只有一種訪問方式:序列訪問(sequential access)。在這些系統(tǒng)中,進(jìn)程可以按照順序讀取所有的字節(jié)或文件中的記錄,但是不能跳過并亂序執(zhí)行它們。順序訪問文件是可以返回到起點(diǎn)的,需要時(shí)可以多次讀取該文件。當(dāng)存儲(chǔ)介質(zhì)是磁帶而不是磁盤時(shí),順序訪問文件很方便。
在使用磁盤來存儲(chǔ)文件時(shí),可以不按照順序讀取文件中的字節(jié)或者記錄,或者按照關(guān)鍵字而不是位置來訪問記錄。這種能夠以任意次序進(jìn)行讀取的稱為隨機(jī)訪問文件(random access file)。許多應(yīng)用程序都需要這種方式。
隨機(jī)訪問文件對(duì)許多應(yīng)用程序來說都必不可少,例如,數(shù)據(jù)庫(kù)系統(tǒng)。如果乘客打電話預(yù)定某航班機(jī)票,訂票程序必須能夠直接訪問航班記錄,而不必先讀取其他航班的成千上萬條記錄。
有兩種方法可以指示從何處開始讀取文件。第一種方法是直接使用 read 從頭開始讀取。另一種是用一個(gè)特殊的 seek 操作設(shè)置當(dāng)前位置,在 seek 操作后,從這個(gè)當(dāng)前位置順序地開始讀文件。UNIX 和 Windows 使用的是后面一種方式。
5. 文件屬性
文件包括文件名和數(shù)據(jù)。除此之外,所有的操作系統(tǒng)還會(huì)保存其他與文件相關(guān)的信息,如文件創(chuàng)建的日期和時(shí)間、文件大小。我們可以稱這些為文件的屬性(attributes)。有些人也喜歡把它們稱作 元數(shù)據(jù)(metadata)。文件的屬性在不同的系統(tǒng)中差別很大。文件的屬性只有兩種狀態(tài):設(shè)置(set) 和 清除(clear)。下面是一些常用的屬性:
沒有一個(gè)系統(tǒng)能夠同時(shí)具有上面所有的屬性,但每個(gè)屬性都在某個(gè)系統(tǒng)中采用。
前面四個(gè)屬性(保護(hù),口令,創(chuàng)建者,所有者)與文件保護(hù)有關(guān),它們指出了誰(shuí)可以訪問這個(gè)文件,誰(shuí)不能訪問這個(gè)文件。
保護(hù)(File Protection):用于保護(hù)計(jì)算機(jī)上有價(jià)值數(shù)據(jù)的方法。文件保護(hù)是通過密碼保護(hù)文件或者僅僅向特定用戶或組提供權(quán)限來實(shí)現(xiàn)。 |
在一些系統(tǒng)中,用戶必須給出口令才能訪問文件。標(biāo)志(flags)是一些位或者短屬性能夠控制或者允許特定屬性。
- 隱藏文件位(hidden flag)表示該文件不在文件列表中出現(xiàn)。
- 存檔標(biāo)志位(archive flag)用于記錄文件是否備份過,由備份程序清除該標(biāo)志位;若文件被修改,操作系統(tǒng)則設(shè)置該標(biāo)志位。用這種方法,備份程序可以知道哪些文件需要備份。
- 臨時(shí)標(biāo)志位(temporary flag) 允許文件被標(biāo)記為是否允許自動(dòng)刪除當(dāng)進(jìn)程終止時(shí)。
記錄長(zhǎng)度(record-length)、鍵的位置(key-position)和鍵的長(zhǎng)度(key-length)等字段只能出現(xiàn)在用關(guān)鍵字查找記錄的文件中。它們提供了查找關(guān)鍵字所需要的信息。
不同的時(shí)間字段記錄了文件的創(chuàng)建時(shí)間、最近一次訪問時(shí)間以及最后一次修改時(shí)間,它們的作用不同。例如,目標(biāo)文件生成后被修改的源文件需要重新編譯生成目標(biāo)文件。這些字段提供了必要的信息。
當(dāng)前大小字段指出了當(dāng)前的文件大小,一些舊的大型機(jī)操作系統(tǒng)要求在創(chuàng)建文件時(shí)指定文件最大值,以便讓操作系統(tǒng)提前保留最大存儲(chǔ)值。但是一些服務(wù)器和個(gè)人計(jì)算機(jī)卻不用設(shè)置此功能。
6. 文件操作
使用文件的目的是用來存儲(chǔ)信息并方便以后的檢索。對(duì)于存儲(chǔ)和檢索,不同的系統(tǒng)提供了不同的操作。以下是與文件有關(guān)的最常用的一些系統(tǒng)調(diào)用:
- Create,創(chuàng)建不包含任何數(shù)據(jù)的文件。調(diào)用的目的是表示文件即將建立,并對(duì)文件設(shè)置一些屬性。
- Delete,當(dāng)文件不再需要,必須刪除它以釋放內(nèi)存空間。為此總會(huì)有一個(gè)系統(tǒng)調(diào)用來刪除文件。
- Open,在使用文件之前,必須先打開文件。這個(gè)調(diào)用的目的是允許系統(tǒng)將屬性和磁盤地址列表保存到主存中,用來以后的快速訪問。
- Close,當(dāng)所有進(jìn)程完成時(shí),屬性和磁盤地址不再需要,因此應(yīng)關(guān)閉文件以釋放表空間。很多系統(tǒng)限制進(jìn)程打開文件的個(gè)數(shù),以此達(dá)到鼓勵(lì)用戶關(guān)閉不再使用的文件。磁盤以塊為單位寫入,關(guān)閉文件時(shí)會(huì)強(qiáng)制寫入最后一塊,即使這個(gè)塊空間內(nèi)部還不滿。
- Read,數(shù)據(jù)從文件中讀取。通常情況下,讀取的數(shù)據(jù)來自文件的當(dāng)前位置。調(diào)用者必須指定需要讀取多少數(shù)據(jù),并且提供存放這些數(shù)據(jù)的緩沖區(qū)。
- Write,向文件寫數(shù)據(jù),寫操作一般也是從文件的當(dāng)前位置開始進(jìn)行。如果當(dāng)前位置是文件的末尾,則會(huì)直接追加進(jìn)行寫入。如果當(dāng)前位置在文件中,則現(xiàn)有數(shù)據(jù)被覆蓋,并且永遠(yuǎn)消失。
- append,使用 append 只能向文件末尾添加數(shù)據(jù)。
- seek,對(duì)于隨機(jī)訪問的文件,要指定從何處開始獲取數(shù)據(jù)。通常的方法是用 seek 系統(tǒng)調(diào)用把當(dāng)前位置指針指向文件中的特定位置。seek 調(diào)用結(jié)束后,就可以從指定位置開始讀寫數(shù)據(jù)了。
- get attributes,進(jìn)程運(yùn)行時(shí)通常需要讀取文件屬性。
- set attributes,用戶可以自己設(shè)置一些文件屬性,甚至是在文件創(chuàng)建之后,實(shí)現(xiàn)該功能的是 set attributes 系統(tǒng)調(diào)用。
- rename,用戶可以自己更改已有文件的名字,rename 系統(tǒng)調(diào)用用于這一目的。
二、目錄
文件系統(tǒng)通常提供目錄(directories) 或者 文件夾(folders) 用于記錄文件的位置,在很多系統(tǒng)中目錄本身也是文件,下面我們會(huì)討論關(guān)于文件,他們的組織形式、屬性和可以對(duì)文件進(jìn)行的操作。
1. 一級(jí)目錄系統(tǒng)
目錄系統(tǒng)最簡(jiǎn)單的形式是有一個(gè)能夠包含所有文件的目錄。這種目錄被稱為根目錄(root directory),由于根目錄的唯一性,所以其名稱并不重要。在最早期的個(gè)人計(jì)算機(jī)中,這種系統(tǒng)很常見,部分原因是因?yàn)橹挥幸粋€(gè)用戶。下面是一個(gè)單層目錄系統(tǒng)的例子。
該目錄中有四個(gè)文件。這種設(shè)計(jì)的優(yōu)點(diǎn)在于簡(jiǎn)單,并且能夠快速定位文件,畢竟只有一個(gè)地方可以檢索。這種目錄組織形式現(xiàn)在一般用于簡(jiǎn)單的嵌入式設(shè)備(如數(shù)碼相機(jī)和某些便攜式音樂播放器)上使用。
2. 層次目錄系統(tǒng)
對(duì)于簡(jiǎn)單的應(yīng)用而言,一般都用單層目錄方式,但是這種組織形式并不適合于現(xiàn)代計(jì)算機(jī),因?yàn)楝F(xiàn)代計(jì)算機(jī)含有成千上萬個(gè)文件和文件夾。如果都放在根目錄下,查找起來會(huì)非常困難。為了解決這一問題,出現(xiàn)了層次目錄系統(tǒng)(Hierarchical Directory Systems),也稱為目錄樹。通過這種方式,可以用很多目錄把文件進(jìn)行分組。進(jìn)而,如果多個(gè)用戶共享同一個(gè)文件服務(wù)器,比如公司的網(wǎng)絡(luò)系統(tǒng),每個(gè)用戶可以為自己的目錄樹擁有自己的私人根目錄。這種方式的組織結(jié)構(gòu)如下:
根目錄含有目錄 A、B 和 C ,分別屬于不同的用戶,其中兩個(gè)用戶個(gè)字創(chuàng)建了子目錄。用戶可以創(chuàng)建任意數(shù)量的子目錄,現(xiàn)代文件系統(tǒng)都是按照這種方式組織的。
3. 路徑名
當(dāng)目錄樹組織文件系統(tǒng)時(shí),需要有某種方法指明文件名。常用的方法有兩種,第一種方式是每個(gè)文件都會(huì)用一個(gè)絕對(duì)路徑名(absolute path name),它由根目錄到文件的路徑組成。舉個(gè)例子,/usr/ast/mailbox 意味著根目錄包含一個(gè)子目錄usr,usr 下面包含了一個(gè) mailbox。絕對(duì)路徑名總是以 / 開頭,并且是唯一的。在UNIX中,路徑的組件由/分隔。在Windows中,分隔符為\。在 MULTICS 中,它是>。因此,在這三個(gè)系統(tǒng)中,相同的路徑名將被編寫如下
- Windows \usr\ast\mailbox
- UNIX /usr/ast/mailbox
- MULTICS >usr>ast>mailbox
不論使用哪種方式,如果路徑名的第一個(gè)字符是分隔符,那就是絕對(duì)路徑。
另外一種指定文件名的方法是 相對(duì)路徑名(relative path name)。它常常和 工作目錄(working directory) (也稱作 當(dāng)前目錄(current directory))一起使用。用戶可以指定一個(gè)目錄作為當(dāng)前工作目錄。例如,如果當(dāng)前目錄是 /usr/ast,那么絕對(duì)路徑 /usr/ast/mailbox可以直接使用 mailbox 來引用。也就是說,如果工作目錄是 /usr/ast,則 UNIX 命令
- cp /usr/ast/mailbox /usr/ast/mailbox.bak
和命令
- cp mailbox mailbox.bak
具有相同的含義。相對(duì)路徑通常情況下更加方便和簡(jiǎn)潔。而它實(shí)現(xiàn)的功能和絕對(duì)路徑安全相同。
一些程序需要訪問某個(gè)特定的文件而不必關(guān)心當(dāng)前的工作目錄是什么。在這種情況下,應(yīng)該使用絕對(duì)路徑名。
支持層次目錄結(jié)構(gòu)的大多數(shù)操作系統(tǒng)在每個(gè)目錄中有兩個(gè)特殊的目錄項(xiàng). 和 ..,長(zhǎng)讀作 dot 和 dotdot。dot 指的是當(dāng)前目錄,dotdot 指的是其父目錄(在根目錄中例外,在根目錄中指向自己)。可以參考下面的進(jìn)程樹來查看如何使用。
一個(gè)進(jìn)程的工作目錄是 /usr/ast,它可采用 .. 沿樹向上,例如,可用命令
- cp ../lib/dictionary .
把文件 usr/lib/dictionary 復(fù)制到自己的目錄下,第一個(gè)路徑告訴系統(tǒng)向上找(到 usr 目錄),然后向下到 lib 目錄,找到 dictionary 文件
第二個(gè)參數(shù) . 指定當(dāng)前的工作目錄,當(dāng) cp 命令用目錄名作為最后一個(gè)參數(shù)時(shí),則把全部的文件復(fù)制到該目錄中。當(dāng)然,對(duì)于上述復(fù)制,鍵入
- cp /usr/lib/dictionary .
是更常用的方法。用戶這里采用 . 可以避免鍵入兩次 dictionary 。無論如何,鍵入
- cp /usr/lib/dictionary dictionary
也可正常工作,就像鍵入
- cp /usr/lib/dictionary dictionary
一樣。所有這些命令都能夠完成同樣的工作。
4. 目錄操作
不同文件中管理目錄的系統(tǒng)調(diào)用的差別比管理文件的系統(tǒng)調(diào)用差別大。為了了解這些系統(tǒng)調(diào)用有哪些以及它們?cè)鯓庸ぷ鳎旅娼o出一個(gè)例子(取自 UNIX)。
- Create,創(chuàng)建目錄,除了目錄項(xiàng) . 和 .. 外,目錄內(nèi)容為空。
- Delete,刪除目錄,只有空目錄可以刪除。只包含 . 和 ..的目錄被認(rèn)為是空目錄,這兩個(gè)目錄項(xiàng)通常不能刪除
- opendir,目錄內(nèi)容可被讀取。例如,未列出目錄中的全部文件,程序必須先打開該目錄,然后讀其中全部文件的文件名。與打開和讀文件相同,在讀目錄前,必須先打開文件。
- closedir,讀目錄結(jié)束后,應(yīng)該關(guān)閉目錄用于釋放內(nèi)部表空間。
- readdir,系統(tǒng)調(diào)用 readdir 返回打開目錄的下一個(gè)目錄項(xiàng)。以前也采用 read 系統(tǒng)調(diào)用來讀取目錄,但是這種方法有一個(gè)缺點(diǎn):程序員必須了解和處理目錄的內(nèi)部結(jié)構(gòu)。相反,不論采用哪一種目錄結(jié)構(gòu),readdir 總是以標(biāo)準(zhǔn)格式返回一個(gè)目錄項(xiàng)。
- rename,在很多方面目錄和文件都相似。文件可以更換名稱,目錄也可以。
- link,鏈接技術(shù)允許在多個(gè)目錄中出現(xiàn)同一個(gè)文件。這個(gè)系統(tǒng)調(diào)用指定一個(gè)存在的文件和一個(gè)路徑名,并建立從該文件到路徑所指名字的鏈接。這樣,可以在多個(gè)目錄中出現(xiàn)同一個(gè)文件。有時(shí)也被稱為硬鏈接(hard link)。
- unlink,刪除目錄項(xiàng)。如果被解除鏈接的文件只出現(xiàn)在一個(gè)目錄中,則將它從文件中刪除。如果它出現(xiàn)在多個(gè)目錄中,則只刪除指定路徑名的鏈接,依然保留其他路徑名的鏈接。在 UNIX 中,用于刪除文件的系統(tǒng)調(diào)用就是 unlink。