Chapter 2 What Is a File System?

2.1 The Fundamentals(基礎(chǔ)知識)

計算機的主要目的是create,manipulate(操縱),store和retrieve數(shù)據(jù)。 file system提供了這些機制。 高級別file system是一種在諸如磁盤之類的永久存儲介質(zhì)上組織,存儲,檢索和管理信息的方法。 file system管理永久性存儲,并構(gòu)成所有操作系統(tǒng)的組成部分。在確定哪種file system適合特定的操作系統(tǒng)時,我們必須權(quán)衡問題的需求和項目的其他約束(沒有絕對的正確,只有最適合的)。牢記文件系統(tǒng)必須實現(xiàn)的抽象目標(biāo)很重要:store(存儲),retrieve(檢索),locate(定位)和manipulate(操作)信息。

2.2 The Terminology(術(shù)語)

Disk:一定大小的永久存儲介質(zhì)。disk還有sector或block size,這是disk可以讀寫的最小單位。大多數(shù)現(xiàn)代disk的block size為512 bytes。

Block:disk或file system可寫的最小單位。file system都是對block進行操作。file system的block大小始終等于或大于disk block size的整數(shù)倍。

Partition:disk上所有block的子集。disk可以具有多個partitions。

Volume:為某些存儲介質(zhì)(如disk)上block集合指定的名稱。也就是說一個volume可以是單個disk上的所有block,也可以是disk上block總數(shù)的一部分,或者甚至可以跨多個disk,并且是幾個disk上的所有block。術(shù)語volume用于表示已使用file system初始化的disk或partitions。

Superblock:file system在其中存儲重要的volumewide信息的volume區(qū)域。superblock通常包含諸如volume的大小,volume的名稱等信息。

Metadata:一個通用術(shù)語,指的是與某物有關(guān)但不直接屬于該物的信息。例如,文件的大小是有關(guān)文件的非常重要的信息,但它不是文件中數(shù)據(jù)的一部分。

Journaling:一種即使在斷電或意外重啟的情況下也可以確保file system metadata正確性的方法。

I-node:file system存儲有關(guān)文件的所有必要metadata的地方。i-node還提供到文件內(nèi)容以及與該文件關(guān)聯(lián)的任何其他數(shù)據(jù)的連接。術(shù)語"i-node"起源于Unix。i-node也稱為 file control block(FCB)或file record。

Extent:disk上的起始block number和連續(xù)blocks的長度。例如,extent可能從block 1000開始并連續(xù)150個blocks。extent始終是連續(xù)的。extent也稱為 block runs。

Attribute:name(作為文本字符串)和與該name關(guān)聯(lián)的value。該value可以具有定義的類型(字符串,整數(shù)等),也可以只是任意數(shù)據(jù)。

2.3 The Abstractions(抽象)

任何file system都有兩個基本概念files和directories。

Files
所有file system必須提供的主要功能是存儲命名的數(shù)據(jù)并以后通過這個名稱檢索數(shù)據(jù)。 我們通常將已命名的數(shù)據(jù)稱為file。 file僅提供file system中最基本的功能。
file是程序永久存儲數(shù)據(jù)的地方。file以其最簡單的形式存儲一條信息。一條信息可以是一些文本(例如,字母,程序源代碼等),圖形圖像,數(shù)據(jù)庫或用戶希望永久存儲的任何字節(jié)集合。 存儲的數(shù)據(jù)大小范圍可能僅從幾個字節(jié)到volume的整個容量。file system應(yīng)該能夠容納大量file,從數(shù)萬到數(shù)百萬。

The Structure of a File
鑒于file的概念,file system對file沒有強加任何結(jié)構(gòu),或者它可能對file的內(nèi)容強制實施大量的結(jié)構(gòu)。非結(jié)構(gòu)化的"raw" file(通常稱為"字節(jié)流")實際上沒有結(jié)構(gòu)。file system只是記錄file的大小,并允許程序按它們想要的任何順序或方式讀取字節(jié)。
非結(jié)構(gòu)化file一次可讀取 1 字節(jié),一次讀取 17 字節(jié),或者程序員需要的任何字節(jié)。此外,不同的程序可能會以不同的方式讀取同一file; file system不關(guān)心它獲取的 I/O 請求的對齊方式或大小。將file視為非結(jié)構(gòu)化流是當(dāng)今file system最常用的方法。
如果file system對file實現(xiàn)結(jié)構(gòu),則通常以records的形式。使用record的概念,程序員指定record的大小和格式,然后該file的所有 I/O 必須發(fā)生在record邊界上,并且是record長度的倍數(shù)。其他系統(tǒng)允許程序創(chuàng)建VSAM(虛擬順序訪問方法)和ISAM(索引順序訪問方法)文件,它們實際上是file中的數(shù)據(jù)庫。 這些概念通常不會進入通用桌面操作系統(tǒng)。 在討論file system時,我們將不考慮結(jié)構(gòu)化文件。 如果您對此主題感興趣,則不妨查看有關(guān)大型機操作系統(tǒng)(例如MVS,CICS,CMS和VMS)的文獻。

File Metadata
file的名稱是metadata,因為它是關(guān)于file的一條信息,不在組成file的字節(jié)流中。 關(guān)于file的metadata還有其他幾個部分,例如owner,security access controls,date of last modification,creation time和size。
除了存儲file內(nèi)容之外,file system還需要一個位置來存儲此metadata。 通常,file system將file metadata存儲在i-node中。


2-1.png

圖2-1繪制了i-node,其包含的內(nèi)容及其數(shù)據(jù)之間的關(guān)系。

The Data of a File
存儲在i-node中最重要的信息是與file中數(shù)據(jù)(即disk上的位置)的連接。 i-node通過跟蹤disk上屬于該file的block list來引用file的內(nèi)容。 file在較高級別上顯示為連續(xù)的字節(jié)流,但是包含file數(shù)據(jù)的block在disk上可能不是連續(xù)的。 i-node包含file system用來從file中的邏輯位置(例如,字節(jié)偏移量11,239)映射到disk上的物理位置的信息。


2-2.png

圖2-2有助于說明(我們假設(shè)file system block size為1024字節(jié))。 如果我們想從file的4096位置讀取,我們需要找到file的第四個block,因為file的4096位置除以file system block size為4。i-node包含組成file的block list。 稍后我們將看到,i-node可以告訴我們file第四block的磁盤地址。 然后,file system必須要求disk讀取該block。最后,在檢索到數(shù)據(jù)之后,file system可以將數(shù)據(jù)傳遞回用戶。

當(dāng)請求讀?。ɑ?qū)懭耄┎辉趂ile system block邊界上的數(shù)據(jù)時,file system必須將文件位置四舍五入到block的開頭。然后,當(dāng)file system將數(shù)據(jù)復(fù)制到block中或從block復(fù)制數(shù)據(jù)時,file system必須添加original position距block開頭的offset。如果我們使用file offset 4732而不是4096,則仍需要讀取file的第四個block。 但是在獲得第四個block之后,我們將使用第四個block中字節(jié)offset 636(4732 - 4096)處的數(shù)據(jù)。

當(dāng)對I/O的請求跨越多個block(例如,讀取8192字節(jié))時,file system必須找到許多block的位置。 如果file system做得很好,則block在disk上將是連續(xù)的。 對disk上連續(xù)block的請求提高了對磁盤執(zhí)行I/O的效率。

The Block Map
i-node可以通過多種方式存儲對文件數(shù)據(jù)的引用。最簡單的方法是block list,每個file對應(yīng)一個block。
例如,如果file長4096字節(jié),則將需要四個disk blocks。使用虛擬磁盤塊號,i-node可能類似于表2-1。
通常,一個i-node將直接在該i-node中存儲4到16個block引用。 由于大多數(shù)file的量級通常在8K以下,因此直接在i-node中存儲一些block地址可簡化查找file數(shù)據(jù)的過程。


2-3.png

i-node只能存儲有限數(shù)量的block地址,因此限制了file可以包含的數(shù)據(jù)量。為了克服在i-node中存儲block地址的空間限制,i-node可以使用indirect blocks。 當(dāng)使用indirect blocks時,i-node將存儲indirect blocks的block地址(即指向該block的指針),而不是數(shù)據(jù)block的地址。 indirect blocks包含指向構(gòu)成file數(shù)據(jù)的block的指針。 indirect blocks不包含用戶數(shù)據(jù),僅包含用戶數(shù)據(jù)的block的指針。 因此,通過一個disk block地址,i-node可以訪問更多數(shù)量的數(shù)據(jù)block。
indirect block可以引用的數(shù)據(jù)block數(shù)等于file system block size除以disk block addresses的大小。在32位file system中,disk block addresses為4字節(jié)(32位)。在64位file system中,它們是8個字節(jié)(64位)。因此,給定file system block size為1024字節(jié),block addresses大小為64位,則indirect block可以引用128個block。
Double-indirect blocks使用與indirect blocks相同的原理。i-node包含double-indirect block的地址,double-indirect block包含指向indirect blocks的指針,而indirect blocks又包含指向文件數(shù)據(jù)塊的指針。double-indirect block是指indirect blocks,就像indirect blocks是指數(shù)據(jù)塊一樣。double-indirect block可以引用的indirect blocks數(shù)與indirect blocks可以引用的數(shù)據(jù)塊數(shù)相同。
也就是說,double-indirect block中的塊地址數(shù)是file system塊大小除以磁盤塊地址大小。在上面給出的示例中,一個1024字節(jié)的塊文件系統(tǒng)具有8字節(jié)(64位)的塊地址,一個double-indirect block可以包含對128個indirect blocks的引用。當(dāng)然,所引用的每個indirect blocks都可以引用相同數(shù)量的數(shù)據(jù)塊。因此,使用我們提供的數(shù)字,double-indirect block允許我們映射的數(shù)據(jù)量為
128 indirect blocks * 128 data blocks per indirect block = 16,384 data blocks
16 MB with 1K file system blocks.
加載數(shù)據(jù)塊后,block_offset值將使我們索引到與原始文件位置相對應(yīng)的確切字節(jié)偏移。

Extents
管理從字節(jié)流中的邏輯位置到disk上data blocks的映射的另一種技術(shù)是使用范圍列表。擴展區(qū)列表類似于前面描述的簡單塊列表,不同之處在于每個塊地址不僅針對單個塊,而且針對一系列塊。即,將每個塊地址指定為起始塊和長度(表示為起始塊之后的連續(xù)塊數(shù))。擴展區(qū)的大小通常大于簡單的塊地址,但可能能夠映射更大的磁盤空間區(qū)域。
例如,如果文件系統(tǒng)使用8字節(jié)的塊地址,則擴展區(qū)可能具有2字節(jié)的長度字段,從而允許該擴展區(qū)最多映射65,536個連續(xù)的文件系統(tǒng)塊。 10字節(jié)的擴展區(qū)大小不是最佳的,因為它不能將任何文件系統(tǒng)塊大小均分為2的冪。為了最大化可以容納在單個塊中的擴展區(qū)的數(shù)量,可以壓縮擴展區(qū)。存在多種方法,但是一種簡單的壓縮方法是截斷塊地址并壓縮長度字段。例如,對于64位塊地址,可以將塊地址縮減為48位,從而為16位長度字段留出足夠的空間。這種方法的缺點是,它減少了文件系統(tǒng)可以處理的最大數(shù)據(jù)量。但是,如果考慮到典型的塊大小為1024字節(jié)或更大,那么我們發(fā)現(xiàn)實際上文件系統(tǒng)將能夠?qū)ぶ范噙_(dá)2更大,則可以尋址58 字節(jié)的數(shù)據(jù)(如果塊大小更多)。這是因為必須將塊地址乘以塊大小才能計算出磁盤上的字節(jié)偏移量。根據(jù)系統(tǒng)其余部分的需求,這可能是可以接受的。
盡管擴展區(qū)列表是引用大量數(shù)據(jù)的更緊湊的方式,但它們可能仍需要使用間接或雙間接塊。如果文件系統(tǒng)高度分散,每個擴展區(qū)只能映射幾個數(shù)據(jù)塊,則必須使用間接和雙間接塊。使用范圍列表的一個缺點是定位特定文件位置可能需要掃描大量范圍。因為擴展區(qū)的長度是可變的,所以在定位特定位置時,文件系統(tǒng)必須從第一個擴展區(qū)開始并掃描所有擴展區(qū),直到找到覆蓋感興趣位置的擴展區(qū)。對于使用雙間接塊的大文件,這可能會令人望而卻步。緩解此問題的一種方法是將擴展區(qū)的大小固定在文件的雙間接范圍內(nèi)。

2.4 Basic File System Operations
files和directories的兩個基本抽象構(gòu)成了file system可以操作的基礎(chǔ)。 file system可以對files和directories執(zhí)行許多操作。 所有file system都必須提供一些basic level的支持。 除了最基本的file system原語之外,還包括其他功能,擴展名和更復(fù)雜的操作。
在對file system操作的討論中,我們著重于file system必須實現(xiàn)的內(nèi)容,而不一定是相應(yīng)的user-level操作。 例如,在file system的context中打開files需要引用directory和name,但是在user level,所需要的只是代表文件名的字符串。 file system的user level API與file system實現(xiàn)的內(nèi)容之間有著密切的關(guān)聯(lián),但是它們并不相同。

Initialization
file system必須提供的第一個操作是在給定volume上創(chuàng)建空file system的方法。file system使用要初始化的volume的大小以及用戶指定的任何選項來確定其內(nèi)部數(shù)據(jù)結(jié)構(gòu)的size和placement。這些初始數(shù)據(jù)結(jié)構(gòu)的placement可能會顯著改善或降低性能。
通常,OS提供了一種方法來找出以多個device blocks表示的volume的大小。然后,此信息用于計算各種數(shù)據(jù)結(jié)構(gòu)的大小,例如free/used block map(通常是bitmap),i-nodes的數(shù)量(如果已預(yù)先分配)以及journal area的大小(如果存在)。在計算這些數(shù)據(jù)結(jié)構(gòu)的大小之后,file system可以決定將它們放置在volume中的何處。file system將這些結(jié)構(gòu)的locations以及volume的大小,volume的狀態(tài)(clean或dirty)以及其他file system全局信息放置到superblock數(shù)據(jù)結(jié)構(gòu)中。file system通常將superblock寫入volume中的已知位置。
file system初始化還必須創(chuàng)建一個空的top-level directory。如果沒有top-level directory,那么在安裝file system以供正常使用時,將沒有容器存放創(chuàng)建的內(nèi)容。top-level directory通常稱為的root directory (或簡稱為 root file system)。表達(dá)式“root directory”來自file system directory層次結(jié)構(gòu)的概念,即inverted tree,top-level directory是該tree的root。除非root directory始終位于volume上的固定位置,否則root directory的i-node號(或地址)也必須存儲在superblock中。
初始化file system的任務(wù)可以作為單獨的用戶程序完成,也可以是核心file system代碼的一部分。無論如何,初始化file system只是將volume準(zhǔn)備為一個空容器,準(zhǔn)備接受file和directory的創(chuàng)建。file system一旦初始化,就可以“mounted”。

Mounting
掛載file system是訪問raw device,讀取superblock和file system metadata,為訪問volume做準(zhǔn)備。掛載file system需要格外小心,因為掛載的file system的狀態(tài)未知并且可能已損壞。file system的superblock通常包含file system的狀態(tài)。如果file system已正確關(guān)閉,則superblock將指示該volume是clean的,不需要進行一致性檢查。關(guān)閉不正確的file system應(yīng)表明該volume已dirty,必須對其進行檢查。
dirty file system的驗證階段非常重要。如果安裝了損壞的file system,則損壞的數(shù)據(jù)可能導(dǎo)致對用戶數(shù)據(jù)的進一步損害,甚至導(dǎo)致file system執(zhí)行非法操作,甚至使系統(tǒng)崩潰。掛載之前驗證file system有效的重要性不能被夸大。驗證并可能修復(fù)損壞的file system的任務(wù)通常是非常復(fù)雜的。journaled file system可以replay其log以確保file system是一致的,但是在繼續(xù)操作之前,它仍應(yīng)驗證其他數(shù)據(jù)結(jié)構(gòu)。由于完整file system檢查的復(fù)雜性,因此通常實現(xiàn)一個單獨的程序,即file system檢查程序。對file system進行完全驗證可能會花費大量時間,尤其是遇到比較大的volume時。幸運的是,只有當(dāng)superblock指示該volume dirty時,才需要進行此類冗長的檢查和修復(fù)操作。
file system確定給定的volume有效后,就必須使用磁盤上的數(shù)據(jù)結(jié)構(gòu)來構(gòu)造內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),以允許其訪問該volume。通常,file system將構(gòu)建superblock的internal version,以及對root directory和free/used block map結(jié)構(gòu)的引用。Journaled file system還必須加載有關(guān)log的信息。file system保持的內(nèi)存狀態(tài)允許其余的OS訪問該volume的內(nèi)容。
file system如何與其余OS連接的詳細(xì)信息往往取決于OS。向file system提供對volume的handle或reference,然后啟動對volume的訪問,從而允許其讀入并驗證file system數(shù)據(jù)結(jié)構(gòu)。當(dāng)file system確定該volume可訪問時,它將返回OS并掛接其操作,以便OS可以調(diào)用file system以執(zhí)行引用該volume上file的操作。

Unmounting
與mounting file system相對應(yīng),還有一個unmount操作。unmount file system涉及將與volume關(guān)聯(lián)的所有內(nèi)存中數(shù)據(jù)刷新到磁盤。一旦將所有內(nèi)存中數(shù)據(jù)寫入volume,就可以說該volume是“clean”。unmount磁盤的最后一個操作是標(biāo)記superblock,以指示發(fā)生了正常關(guān)閉。通過以這種方式標(biāo)記superblock,file system可確保就其所知,磁盤未損壞,這使下一次Mounting操作可以達(dá)到一定程度的完整性。由于未標(biāo)記為clean的file system可能會損壞,因此重要的是,file system應(yīng)完全unmount所有volume。標(biāo)記superblock之后,除非重新mount該volume,否則系統(tǒng)不應(yīng)訪問該volume。

Creating Files
mounting新初始化的volume后,該volume上沒有任何內(nèi)容。
因此,file system必須支持的第一個主要操作是create files的能力。create files需要兩個基本信息:用于創(chuàng)建文件的directory和file name。借助這兩條信息,file system可以創(chuàng)建一個表示文件的i-node,然后可以在directory中添加file name/i-node pair。附加參數(shù)可以指定文件訪問權(quán)限,文件模式或file system的其他標(biāo)志。
在為file分配i-node后,file system必須填寫相關(guān)信息。存儲創(chuàng)建時間的file system必須記錄該時間,并且文件大小必須初始化為零。如果需要,file system還必須在i-node中記錄所有權(quán)和安全性信息。
create files不會為文件contents保留存儲空間。當(dāng)數(shù)據(jù)寫入文件時,分配空間以容納數(shù)據(jù)。文件的創(chuàng)建僅分配i-node,并將文件輸入到包含該i-node的directory中。

Creating Directories
create directory類似于create file,只是稍微復(fù)雜一點。與文件一樣,file system必須分配一個i-node以記錄有關(guān)directory的metadata,并在其parent directory中輸入directory的名稱。
但是,與文件不同,必須初始化directory的contents。初始化directory可能很簡單,例如,將directory存儲為list時,或者可能很復(fù)雜,例如,使用B-tree來存儲directory的contents時。directory還必須包含一個指向其parent directory的reference。reference只是返回parent directory的i-node號。存儲到parent directory的鏈接使file system層次結(jié)構(gòu)的導(dǎo)航更加簡單。程序可以遍歷目錄層次結(jié)構(gòu),大多數(shù)POSIX-style的file system都將到parent directory的link存儲為該directory中的".."。"."始終存在,并且指directory本身。
create directory是一項基本操作,它允許用戶構(gòu)建層次結(jié)構(gòu)來表示其信息的組織。directory必須維護對其parent directory的reference才能啟用層次結(jié)構(gòu)的導(dǎo)航。create directory對于分層file system的概念至關(guān)重要。

Opening Files
打開現(xiàn)有文件可能是file system最常用的操作。打開文件可能會有些復(fù)雜。打開文件是由兩個操作組成。第一個操作是lookup,引用directory和name,然后在該directory中查找name。Lookup name涉及遍歷directory數(shù)據(jù)結(jié)構(gòu),以查找名稱是否存在,如果存在,則返回關(guān)聯(lián)的i-node。lookup操作的效率很重要。許多directory只有幾個文件,因此數(shù)據(jù)結(jié)構(gòu)的選擇可能不那么重要,但是大型服務(wù)器通常具有包含數(shù)千個directory。在那些情況下,目錄數(shù)據(jù)結(jié)構(gòu)的選擇可能至關(guān)重要。
給定一個i-node號,open操作的后半部分涉及驗證用戶可以訪問該文件。涉及檢查權(quán)限是否被允許這樣做。如果檢查成功,則file system將分配一個內(nèi)存中的結(jié)構(gòu)來維護有關(guān)文件訪問的狀態(tài)(例如,文件是否以read-only打開,appending等)。
open操作的結(jié)果是一個handle,請求程序可以使用該handle對文件進行I/O操作。file system返回的handle由操作系統(tǒng)的higher-level portions使用。操作系統(tǒng)具有存儲此handle的其他結(jié)構(gòu)。user-level使用的handle與open操作返回的內(nèi)部handle間接相關(guān)。操作系統(tǒng)通常在到達(dá)file system handle之前,通過多個表映射user-level file descriptor(fd)。

Writing to Files
file system的write操作允許程序?qū)?shù)據(jù)存儲在文件中。將數(shù)據(jù)write文件所需的參數(shù)是對文件的引用,在文件中寫入數(shù)據(jù)的position,memory buffer以及要寫入的數(shù)據(jù)length。write文件等同于要求file system將data chunk復(fù)制到文件中的permanent location。
write操作將占用memory buffer,并將該數(shù)據(jù)寫入指定文件中的指定position。如果已經(jīng)在文件的末尾,則需要先擴大文件,然后才能進行寫操作。增加文件的大小涉及分配足夠的disk blocks來保存數(shù)據(jù),并將這些blocks添加到文件"owned"的block list中。
擴大文件會導(dǎo)致對free/used block list,文件i-node以及事務(wù)中涉及的任何indirect或double-indirect blocks進行更新。file system的superblock也可能會被修改。
一旦有足夠的數(shù)據(jù)空間,file system就必須從文件中的邏輯位置映射到disk block address。使用physical block address,file system可以將數(shù)據(jù)寫入底層設(shè)備,從而使其成為永久性文件。
write完成后,內(nèi)核維護的文件offset將增加寫入的字節(jié)數(shù)。

Reading Files
read操作允許程序訪問文件的contents。read的參數(shù)與write的參數(shù)相同:指向文件的handle,position,memory buffer和length。
read操作比write操作簡單,因為read操作根本不會修改磁盤。read操作所需要做的就是將文件中的logical position映射到相應(yīng)的disk address。有了physical disk address,file system可以從基礎(chǔ)設(shè)備檢索數(shù)據(jù),并將其放入user’s buffer。
read操作還將文件position增加read的數(shù)據(jù)量。

Deleting Files
delete file是file system需要支持的下一個邏輯操作。delete file的最常見方法是傳遞文件名。如果名稱存在,則delete file有兩個階段。第一階段是從文件所在的directory中刪除該文件的名稱。刪除該名稱可防止其他程序在刪除文件后打開該文件。刪除名稱后,該文件將標(biāo)記為刪除。
delete file的第二階段僅在沒有其他程序打開文件handle的時候發(fā)生。在沒有其他人引用該文件的情況下,可以釋放該文件使用的資源。在此階段,file system可以將文件使用的data blocks返回到free block pool,并將文件的i-node返回到free i-node list。
必須將文件刪除分為兩個階段,因為當(dāng)請求刪除時,文件可能正在打開以供讀取或?qū)懭?。如果file system立即執(zhí)行兩個階段,則文件上的下一個I/O請求將無效(因為data blocks將不再屬于該文件)。使delete操作立即刪除文件會使文件的I/O的語義復(fù)雜化。通過等待直到文件的引用計數(shù)變?yōu)榱阍賱h除與文件關(guān)聯(lián)的資源,系統(tǒng)才能向應(yīng)用程序保證,一旦用戶程序打開文件,它將保持有效的讀寫狀態(tài),直到關(guān)閉文件描述符。
兩階段方法的另一個額外好處是,程序可以為I/O打開一個臨時文件,立即將其刪除,然后繼續(xù)正常的I/O處理。當(dāng)程序退出并且其所有資源都關(guān)閉時,該文件將被正確刪除。這使程序不必?fù)?dān)心在出現(xiàn)錯誤情況時進行清理。

Renaming Files
rename操作是file system必須支持的最復(fù)雜的操作。rename操作所需的參數(shù)是source directory handle,,source file name,destination directory handle和destination file name。
在進行rename操作之前,必須對參數(shù)進行大量驗證。如果file system是多線程的,則必須鎖定整個file system,以防止其他操作影響rename操作的狀態(tài)。
如果source directory和destination directory handles相同,則需要進行的第一個驗證是source file name和destination file name是否不同。如果source directory和destination directory不同,則source name和destination name相同是可以接受的。
驗證的下一步是檢查source name是否引用了directory。如果是,則destination directory不能是source directory的subdirectory。要進行此檢查,需要從destination directory一直到root directory遍歷層次結(jié)構(gòu),并確保source name不是destination的root directory。此操作最復(fù)雜,需要鎖定整個file system。
只有滿足上述復(fù)雜的標(biāo)準(zhǔn)集,才能開始rename操作。rename的第一步是刪除destination name(如果它指向file或空directory)。
rename操作本身涉及從source directory中刪除source name,然后將destination name插入到destination directory中。此外,如果source name引用directory,則file system必須將對source directory的parent directory的引用更新。如果不這樣做,將導(dǎo)致目錄層次結(jié)構(gòu)發(fā)生變化,從而導(dǎo)致在導(dǎo)航目錄層次結(jié)構(gòu)時出現(xiàn)不可預(yù)測的結(jié)果。

Reading Metadata
read metadata操作是一項內(nèi)部管理功能,它允許程序訪問有關(guān)文件的信息。該函數(shù)的參數(shù)只是對file的引用。返回的信息因系統(tǒng)而異,但本質(zhì)上是i-node結(jié)構(gòu)中某些字段的副本(上次修改時間,所有者,安全信息等)。在POSIX中此操作稱為 stat() 。

Writing Metadata
如果能夠讀取file的metadata,則很有可能需要對其進行修改。write metadata操作允許程序修改file的i-node中的字段。在用戶級別,可能會有許多不同的函數(shù)來修改每個字段(chown(), chmod(), utimes()等),但是內(nèi)部只需要一個函數(shù)即可。當(dāng)然,并非i-node的所有字段都可以修改。

Opening Directories
正如對file內(nèi)容的訪問是使用 open() 一樣,directory有類似操作,通常稱為 opendir()。 "opening" directory的概念很簡單。directory需要提供一種機制來訪問directory中存儲的file列表,而opendir操作是用于授予對directory訪問權(quán)限的操作。opendir的參數(shù)只是對directory的引用。請求程序必須檢查其權(quán)限。如果沒有什么阻止該操作,則返回一個handle,請求程序可以使用該handle來調(diào)用readdir操作。

Reading Directories
readdir操作枚舉directory的內(nèi)容。 沒有相應(yīng)的WriteDir(嚴(yán)格來說,create和makedir都"write" directory)。 readdir操作必須遍歷directory,返回存儲在directory中的連續(xù)name/i-node pairs(以及可能還存儲在directory中的其他信息)。 返回entries的順序取決于基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。
如果file system具有directory entries的復(fù)雜數(shù)據(jù)結(jié)構(gòu),則在調(diào)用readdir時,file system還會保留一些關(guān)聯(lián)狀態(tài)(分配在opendir中)。每次對readdir的調(diào)用都會更新狀態(tài)信息,以便在下一次對readdir的調(diào)用時,可以讀取并返回directory中的后續(xù)元素。沒有readdir,程序?qū)o法導(dǎo)航file system層次結(jié)構(gòu)。

Basic File System Operation Summary
本節(jié)討論的file system操作描述了任何file system功能的基線。任何file system必須提供的第一個操作是initialize volume的方法。Mounting file system,以便的操作系統(tǒng)其余部分可以訪問它,這是接下來需要的最基本的操作。Creating files和directories是file system功能的基礎(chǔ)。Writing和reading數(shù)據(jù)使用戶可以從永久性存儲中存儲和檢索信息。delete和rename操作提供了管理、操作,文件和目錄的機制。read metadata和write metadata功能允許用戶讀取和修改file system維護的有關(guān)文件的信息。最后, opendir 和 readdir 調(diào)用使用戶可以迭代并枚舉directory層次結(jié)構(gòu)中的文件。這組基本操作提供了file system所需的最少功能。

2.5 Extended File System Operations

僅提供純file和directory的最基本功能的file system幾乎不值得討論。有許多feature可以增強file system的功能。本節(jié)討論基本file system的一些擴展以及現(xiàn)代file system支持的一些更高級的功能。

Symbolic Links
許多file system實現(xiàn)的一項功能是symbolic link。symbolic link是一種在file system中創(chuàng)建僅引用另一個文件的命名實體。也就是說,symbolic link是directory中的名稱entity,但是symbolic link包含應(yīng)打開的另一個文件的名稱,而不是關(guān)聯(lián)的i-node引用文件。例如,如果directory包含一個名為 Feeder 的symbolic link,并且該symbolic link引用了一個名為Breeder的文件,則每當(dāng)程序打開Feeder時,file system就會將其透明地轉(zhuǎn)換為的打開 Breeder。如果將文件 Breeder 重命名為 Breeder.old,則symbolic link Feeder 將保持懸空狀態(tài)(仍指向 Breeder),因此將不再起作用。盡管有這個問題,symbolic link還是非常方便的。

Hard Links
另一種形式的鏈接稱為hard link。hard link也稱為alias。hard link是與文件的更牢固的連接。使用hard link,directory中的名稱entity僅包含其他文件的i-node號,而不是其自身的i-node(實際上,鏈接本身沒有i-node )。這種連接非常牢固:即使移動或重命名了原始文件,其i-node地址也保持不變,因此與文件的連接永遠(yuǎn)也不會被破壞。即使刪除了原始文件,file system也會保留引用計數(shù),并且僅在引用計數(shù)為零(意味著沒有人引用該文件)時才刪除該文件。在不能斷開與文件的連接的情況下,最好使用hard link。

Dynamic Links
第三種link,即dynamic link,實際上只是具有特殊屬性的symbolic link。如前所述,symbolic link包含對另一個文件的引用,并且該引用存儲為文本字符串。Dynamic link通過解釋文本字符串增加了另一種間接訪問級別。file system可以通過幾種方式解釋鏈接的文本。一種方法是將字符串視為environment variable,然后用匹配的environment variable的內(nèi)容替換鏈接的文本。

Memory Mapping of Files
某些操作系統(tǒng)支持的另一個功能是能夠map文件。Memory mapping文件會在程序的地址空間中創(chuàng)建virtual memory區(qū)域,并且該內(nèi)存區(qū)域中的每個字節(jié)都對應(yīng)于文件的字節(jié)。如果程序映射的文件從地址0x10000開始,則內(nèi)存地址0x10000等效于文件中offset 0 byte。同樣,地址0x10400等效于文件中的offset 0x400(1024)。
Unix-style的 mmap()調(diào)用可以選擇將文件的內(nèi)存中副本同步到磁盤,以便將寫入內(nèi)存的數(shù)據(jù)刷新到磁盤。還有用于跨多個進程共享映射文件的標(biāo)志(共享信息的強大功能)。
文件的memory mapping需要OS的virtual memory system和file system之間緊密配合。主要要求是virtual memory system必須能夠從file offset映射到disk上的相應(yīng)block。在代表virtual memory(VM)系統(tǒng)執(zhí)行操作時,file system還可能面臨其他限制。例如,在與memory-mapped file相關(guān)的操作期間,VM系統(tǒng)可能無法容忍來自file system的頁面錯誤或內(nèi)存分配請求(因為VM系統(tǒng)已被鎖定)。這些類型的約束和要求可能會使實現(xiàn)memory-mapped file變得棘手。

Attributes
最近有幾種file systems(OS/2’s HPFS, NT’s NTFS, SGI’s XFS and BFS)支持extended file attributes。 attribute是一個簡單的name(很像一個文件名)和value(任意大小的數(shù)據(jù)塊)。通常,希望與文件一起存儲有關(guān)文件的其他信息,但是修改文件的內(nèi)容是不可行的。例如,當(dāng)Web browser下載image時,它可以將image來源的URL作為attribute存儲。當(dāng)幾個月后您想獲得image的站點時,這將很有用。attribute提供了一種將有關(guān)文件的其他信息與文件相關(guān)聯(lián)的方法。理想情況下,file system應(yīng)允許任意數(shù)量的附加attribute,并允許這些attribute具有任意大小。file system選擇存儲attribute信息的位置取決于file system。例如,HPFS為文件attribute保留一個固定的64K區(qū)域。 BFS和NTFS提供了更大的靈活性,可以將attribute存儲在磁盤上的任何位置。

Indexing
File attributes允許用戶將其他信息與file相關(guān)聯(lián),但是file system可以通過擴展文件attribute來做更多工作,以幫助用戶管理和查找他們的信息。如果file system也為attribute建立index,則可以發(fā)出有關(guān)attribute內(nèi)容的查詢。例如,如果我們添加了 關(guān)鍵字 向一組文件中attribute,并且對關(guān)鍵字attribute進行了index,那么用戶可以發(fā)出查詢,詢問哪些文件包含各種關(guān)鍵字,無論它們在層次結(jié)構(gòu)中的位置如何。
與良好的查詢語言配合使用時,index為file system提供了強大的替代接口。使用查詢,用戶不限于瀏覽固定的文件層次結(jié)構(gòu);取而代之的是,他們可以發(fā)出查詢來查找他們想要查看的文件的工作集,而不管文件的位置如何。

Journaling/Logging
避免corruption的方法是journaling。journaling是從數(shù)據(jù)庫世界中借來的一種技術(shù),它通過批處理更改組并將它們一次提交到transaction log中來避免corruption。批量更改保證了多個更改的原子性。原子性保證使file system可以保證操作完全發(fā)生或根本不發(fā)生。此外,如果確實發(fā)生crash,則系統(tǒng)僅需要replay transaction log即可將系統(tǒng)恢復(fù)到已知狀態(tài)。Replaying log是一項最多需要幾秒鐘的操作,這比非journal file system必須進行的file system檢查要快得多。

Guaranteed Bandwidth/Bandwidth Reservation
保證multimedia applications的高帶寬I/O的愿望促使某些file system設(shè)計人員提供特殊的hooks,以使應(yīng)用程序可以保證他們將獲得一定數(shù)量的I/O帶寬(在硬件限制的范圍內(nèi))。為此,file system需要大量有關(guān)其使用的底層硬件功能的知識,并且必須調(diào)度I/O請求。

Access Control Lists
Access control lists(ACL)提供了擴展的機制,用于指定誰可以訪問文件以及他們?nèi)绾卧L問文件。在某些設(shè)置中,傳統(tǒng)的POSIX方法具有三組權(quán)限(對于文件的owner,owner所在的group,以及其他所有人),這是不夠的。Access control lists指定任何人對文件的確切訪問級別。與POSIX security model中定義的廣泛劃分相比,這可以對文件的訪問進行細(xì)粒度的控制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容