1. 程式人生 > >現代作業系統: 第四章 檔案系統

現代作業系統: 第四章 檔案系統

在多程式多使用者的系統上,讀取資料有以下問題:

  • 如何找到資訊?
  • 如何防止一個使用者讀取另一個使用者的資料
  • 如何知道哪些塊是空閒的?

通過前面的學習, 我們知道 作業系統對處理器進行抽象 建立了程序這個概念; 通過對物理儲存器的抽象建立了 虛擬地址空間的概念, 現在,為了解決問題, 就建立了 檔案 這個抽象概念。

作業系統處理檔案的部分 稱為檔案系統。檔案是授作業系統管理的。有關檔案的構造、命令、訪問、使用、保護、實現和管理方法都是作業系統設計的主要內容。從總體上看,作業系統中的處理檔案的部分稱為檔案系統。

4.1 檔案

4.1.1 檔案命名

如homepage.html, 圓點前面是名字,圓點以後是副檔名,.html表示 這是一個html檔案。在某些系統中,副檔名是一種約定,指定為某一類檔案,但是作業系統並不強制採用這種形式,常見副檔名如下:
在這裡插入圖片描述

4.1.2 檔案結構

檔案有許多構造方式,在圖中列出了常用的三種構造方式:

在這裡插入圖片描述

  • 無結構位元組序列:全都是位元組,其內容含義只有在使用者程式中解釋,UNIX和Windows都採用這種方法
  • 記錄序列:這種結構中,檔案時有固定長度記錄的序列,每個記錄尤其內部結構
  • 樹:檔案由一顆記錄樹構成,每個記錄長度不一,每個記錄的固定位置有一個鍵,通過鍵可以快速查詢,一般在處理商業資料的大型計算機系統中使用。

4.1.3 檔案型別

  • 目錄(或者說資料夾):每個目錄也是一種檔案, 是管理檔案系統結構的系統檔案
  • 普通檔案:一般分為ASCII檔案和二進位制檔案。 ASCII檔案的優勢就是可以顯示和列印, 也是通使用者常用的檔案,如文字。二進位制檔案如視訊圖片等。
  • 字元特殊檔案(character special file):字元特殊檔案和輸入/輸出有關,用於序列I/O型別裝置,如印表機和網路等。
  • 塊特殊檔案(block special file):快特殊檔案用於磁碟類檔案。

下圖是一個可執行二進位制檔案和一個存檔普通檔案的結構,可執行二進位制檔案的結構有:檔案頭、正文、資料、重定位位,符號表。

在這裡插入圖片描述

4.1.1 檔案訪問

  • 早期只有順序訪問
  • 隨機訪問:按照關鍵字位置來訪問記錄, 可以任意跳轉。有兩種方式指示從何處開始讀取檔案,一種是read操作時給出開始檔案位置,另一種是通過seek操作設定訪問的位置。

4.1.5 檔案屬性

所有的作業系統還會儲存其他與檔案相關的資訊,如檔案建立的日期和時間、檔案大小等,這些附加資訊稱為檔案屬性。

在這裡插入圖片描述

4.1.6 檔案操作

在這裡插入圖片描述

4.2 目錄

檔案系統通常提供目錄或資料夾用於記錄檔案的位置。

4.2.1 一級目錄系統

在早期系統或者限制一些簡單的嵌入式系統中,採用,目錄只有一個層級,如下,方形表示目錄檔案,原型表示普通檔案:

在這裡插入圖片描述

4.2.2 層次目錄系統

多數計算機系統都採用多層次目錄系統,如下:

在這裡插入圖片描述

4.2.3 路徑名

在層次目錄系統中,每個檔案都有一個絕對路徑名,它是從根目錄到檔案的路徑,例如 /usr/ast/mailbox。不同系統的路徑的分隔符不同,有 / 或者 \ 或者 > , 如下:

另外一種指定檔名的方法是使用相對路徑。它常常和工作目錄一起使用。每個程序都會有自己的工作目錄。在作業系統的每個目錄有兩個特殊目錄項: “.”和“…”, 讀作dot和dotdot, dot指當前目錄, dotdot指父目錄。

4.2.4 目錄操作

在這裡插入圖片描述

4.3 檔案系統的實現

4.3.1 檔案系統的佈局

檔案系統放在磁碟上,多數磁碟劃分為一個或多個分割槽,每個分割槽有一個獨立的檔案系統。磁碟的0號扇區稱為主引導記錄(Master Boot Record,MBR),用來引導計算機。MBR的結尾是分割槽表,該表給出了每個分割槽的其實和結束位置。表中的一個分割槽標記為活動分割槽,計算機啟動時,BIOS讀入並執行MBR,MBR第一件事就是確定活動分割槽,然後讀入它的第一個塊,稱為引導塊(boot block),然後執行它。引導塊中的程式將裝載該分割槽中的作業系統。為了統一,每個分割槽都從第一個引導塊開始,即使它並不包含作業系統,不過也不排除它未來不會安裝作業系統。

除了都是從引導塊開始,不同檔案系統的磁碟分割槽的佈局是不同的,下圖是一種檔案系統的結構佈局, 第一個是超級塊(superblock),包含了檔案系統的所有關鍵引數,在計算機啟動或者該檔案系統首次使用時,超級快會被讀入記憶體,其中的典型資訊有:檔案系統型別使用的魔數,檔案系統中塊的數量以及其他重要管理資訊,示例圖如下:

在這裡插入圖片描述

接著就是檔案系統中的空閒塊的資訊,列如,可以用點陣圖或指標列表的形式給出。後面跟著的是一組i節點,這是一個數據結構的陣列。最後磁碟的其他部分存放了其他所有的目錄和檔案。

4.3.2 檔案的實現

檔案儲存的關鍵問題是記錄各個檔案分別用到哪些磁碟塊,主要有:連續分配、連結串列分配、採用記憶體中的表進行連結串列分配,i節點。

1. 連續分配

檔案作為一串連續資料塊儲存在磁碟上。簡單且效率高,但是隨著時間分配,磁碟變得零碎,如果某個連續空間比較小,而檔案比較大,就不會放入這個空間,造成浪費。最終形成很多磁碟空洞,這時,如果重新挪動位置壓縮磁碟空間,代價就太大了。因此,這個比較適合一次性寫入的介質。

2. 連結串列分配

磁碟每個塊的第一個字作為指向下一個塊的指標,塊的其他部分存放資料。 連結串列不會浪費空間,但是隨機訪問很慢。

存在的問題:

  1. 在連結串列的分配方案中,經過順序訪問檔案非常方便,但是隨機訪問檔案卻相當緩慢。
  2. 由於每個塊儲存了指標,剩餘部分儲存的位元組就不再是2的整數次冪,而許多程式都是以2的整數次冪讀取磁碟塊,這也會降低效率。

在這裡插入圖片描述

3. 採用記憶體中的表進行連結串列分配

對連結串列分配的優化,就是把每個磁碟塊的指標,存放在記憶體的一個表中,就可以解決連結串列分配的不足。當有連續塊是,就可存放在連續塊中,當連續塊不夠,就指向其餘空閒的塊中。記憶體中這樣的表格稱為 檔案分配表(File Allocation Table, FAT)。 示例圖如下:

在這裡插入圖片描述

不過這種方法的缺點就是必須把整個表存在記憶體中,如果磁碟很大,這個表就會特別大,因此FAT並不怎麼適合大型磁碟中。

4. i節點

給每個檔案賦予一個名字為 i節點(index-node)的資料結構,用來記錄檔案包含了哪些磁碟塊。只要給定i節點,就能找到檔案的所有塊。這種方式的優勢在於,只有檔案被開啟時,其i節點才在記憶體中,從而節省了記憶體。

如果每個i節點只能儲存固定數量的磁碟地址,那麼一個檔案包含的磁碟塊超過了固定數量怎麼辦呢? 其中一種解決辦法就是最後一個地址指向一個包含額外地址的底盤塊,升級版是最後兩個或三個地址都可以指向其他存放地址的磁碟塊,示例圖:

在這裡插入圖片描述

4.3.3 目錄的實現

在讀取檔案前,必須先要開啟檔案,開啟檔案時,作業系統利用使用者給出的路徑名找到相應的目錄項。目錄項中提供了查詢檔案磁碟所需要的資訊。目錄系統地主要功能是把ASCII檔名對映成定位檔案資料所需要的資訊。

要找到檔案,就要根據路徑名去找,路徑就涉及到目錄以及在何處去存放檔案的屬性。實現方式有兩種:1.簡單目錄,即在目錄檔案中有一個固定大小的目錄項列表,每個檔案對應一項,,其中有(固定長度)的檔名、屬性的結構體、磁碟塊的位置的一個或多個地址。 2.對於採用了i節點的系統,可以把屬性存放在i節點中,而不是目錄項中,這樣,目錄項中就只需要存放檔名和i節點號了,這種方式更好。兩種方式的目錄項示例圖如下:

在這裡插入圖片描述

還有另一個問題,就是檔名的長度以及檔名的儲存。也就是說如何處理可變長度檔名字:

第一種簡單的方式就是給予檔名一個固定的長度限制,同時給檔名分配固定大小的目錄空間。但是如果檔名用不了這麼多長度,就白白浪費了。

第二種方式是 每個目錄項前面部分是固定格式的資料,如目錄項長度、檔案屬性,然後接上可變的任意長度的檔名,檔名以特殊字元(通常為0)結束。如下圖圖a, 這個方法的缺點就是每個檔案項的大小不一,如果移走一個檔案,再新來一個檔案,新檔案的檔案項不一定剛好適。

第三種方式就是目錄項有一個固定長度,而將檔名放在目錄後面的堆中,這樣移走一個檔案,下一個檔案進來了,也剛好可以適合這個空隙。不過,就必須對堆進行管理。示例圖如下:

在這裡插入圖片描述

4.3.4 共享檔案

在這裡插入圖片描述

在上圖中,目錄C下有一個檔案和目錄B共享, 有兩種方式,一種是連結(link),共享檔案的所有者是C,但是這個檔案在C的被引用目錄項的計數為2,當在C目錄下去刪除共享檔案時, 如果共享檔案發現計數為2,就不會去刪除這個檔案,而是把計數減1,直到計數為0,才會刪除。這個或者叫硬連結。例圖如下:

另一種方法為符號連結(symbolic linking),或者叫軟連線。通過讓作業系統建立一個型別為LINK的新檔案,並把該檔案放在B的目錄下,得到B與C的檔案存成在一個連結。新的檔案中只包含了它所連結的檔案的路徑名。當B讀取該連結檔案的時候,作業系統檢視到要讀的檔案是LINK型別,則找到該檔案所連結的檔案的名字,並且去讀那個檔案。

在這裡插入圖片描述

4.3.5 日誌結構檔案系統

問題:可見零碎的磁碟從中是及其沒有效率的。

LFS的設計者決定重新設計一種UNIX檔案系統,該系統即使面對一個大部分由於零碎的隨機寫操作組成的任務,統一也能夠充分利用磁碟的頻寬。其基本思想是將整個磁碟結構化為一個日誌。每隔一段時間,別快取在記憶體中所有未決定的寫操作都放到一個單獨的段中,作為在日誌末尾的一個鄰接段寫入磁碟。

4.3.6 日誌檔案系統

儲存一個用於記錄系統下一步需要做什麼的日誌,這樣,如果系統在即將完成任務時崩潰,重新啟動後,可以通過檢視日誌,獲取崩潰前計劃完成的任務,並重新去完成它,完成後擦除日誌項。

4.3.7 虛擬檔案系統

絕大多數UNIX作業系統都在使用虛擬作業系統。概念嘗試將多種檔案系統統一成一個有序的結構。關鍵的思想是抽象出所有檔案系統都共有的部分,並將這部分程式碼放在單獨的一層,該層呼叫底層的實際檔案系統來管理資料。

在這裡插入圖片描述

4.4 檔案系統的管理和優化

4.4.1 磁碟管理優化

幾乎所有的檔案系統都是通過塊來管理儲存的,檔案系統把檔案分割成固定大小的塊。

1.塊大小

如果分配的單元過小,則浪費了空間。如果分配的單元太小,則浪費了磁碟時間。

這個通過研究曲線決定,目前最佳為64k, 如下圖:

在這裡插入圖片描述

2. 記錄空閒塊

第一種方法是採用磁碟塊連結串列,連結串列中每個塊包含儘可能多的空閒磁碟快號。

另一種空閒磁碟管理方法就是採用點陣圖。n個塊的磁碟需要n個位圖。

如果空閒塊傾向於成為一個長的連續分塊的話,則空閒列表系統可以改成記錄連續分塊而不是單個分塊。

在這裡插入圖片描述

3.磁碟配額

為防止人們貪心佔用過多空間,由管理員為每位使用者分配最大擁有檔案和塊的數量,作業系統確保每個使用者不超過分給他們的配額。

在這裡插入圖片描述

4.4.2 檔案系統備份

為了防止檔案系統被破壞,通常需要對檔案進行備份。主要是為了解決兩個問題:

  1. 從以外的災難中恢復
  2. 從錯誤中恢復

同時備份檔案不要防在同一個地方,應在不同的地方儲存,不過又會增加安保的難度,不過這個不在討論之列。

為檔案做備份費時費空間,因此要選擇有意義的目錄,如臨時檔案目錄就不用備份了。備份一些特定目錄或者重要目錄。

其次,對前一次備份沒做更改而再去備份也是一種浪費,因此有了增量轉儲的思想。最簡單的增量轉儲形式就是每週或每月做一次全面備份,而每天只需要對從上一次轉儲後改變的檔案備份即可。不過這個回覆起來比較複雜。所以通常用更復雜的增量轉儲方法。

第三、既然轉儲檔案時海量的,那麼需不需要壓縮也應該考慮。

第四、記錄檔案系統的瞬時快照,賦值關鍵資料結構,其餘留待空閒時在備份

第五、非技術性問題,注意備份檔案的安保。

物理轉儲:從磁碟第0塊開始,直到最後一塊, 全部複製。

邏輯轉儲:從一個或幾個指定目錄開始,遞迴的轉儲給定日期以後更改的檔案及目錄。

4.4.3 檔案系統一致性

一種處理方法就是磁碟塊計數表,使用的塊和空閒的塊, 加起來, 各個位都為1,否則就是一致性出錯。

在這裡插入圖片描述

4.4.4 檔案系統性能

1. 快取記憶體

塊告訴快取邏輯上屬於磁碟,但實際上基於效能考慮儲存在記憶體中。告訴快取塊的換入換出,可參考第二章的FIFO演算法,LRU演算法等頁面置換演算法。 為了防止計算機系統崩潰導致檔案系統破壞,UNIX無限迴圈沒30s呼叫一次sync,強制將修改過的塊立即寫到磁碟,這樣,就算系統崩潰,丟失資料不會超過30s。

2. 塊提前讀取

提前將即將呼叫的塊寫入告訴快取,明顯可以提升執行效率。通常使用與順序讀檔案。對於隨機讀檔案,先按照順序提前讀入,即使一開始錯了也沒關係,然後真正通過讀入的塊的檔案關聯性,去提前載入下一個塊, 從而提升命中率。

3. 減少磁碟臂擺動

不是有可能順序訪問的塊放在一起,最好在一個柱面上,較少磁臂運動時間。

4.4.5 磁碟碎片整理

在初始安裝作業系統後,從磁碟開始位置,一個接著一個地連續安裝了程式和檔案。所有的空閒磁碟空間放在一個單獨的,與被安裝的檔案鄰近的單元裡。但是隨著時間的流逝,檔案被不斷的創建於刪除,於是磁碟會產生很多碎片,檔案與空穴到處都是。定期整理磁碟,減少碎片。

4.5 檔案系統例項

UNIX V7 檔案系統

對於大型檔案,通常採用前面講 i節點 時,圖4-13使用的方法,就是最後幾個地址存放的是另外的塊, 快中存放的還是檔案塊的地址。如果檔案很大,可以使用兩次間接塊甚至三次間接塊,如下圖:

在這裡插入圖片描述

在這裡插入圖片描述

例如查詢目錄 /usr/ast/mbox的過程,如下圖,其中.表示當前目錄的i節點號, …表示父目錄i節點號:

在這裡插入圖片描述