文件系統(tǒng)和虛擬文件系統(tǒng)交換
內(nèi)核的一個(gè)重要職責(zé)就是管理數(shù)據(jù),這些數(shù)據(jù)既包括用戶(hù)數(shù)據(jù)也包括系統(tǒng)數(shù)據(jù)。為了實(shí)現(xiàn)這個(gè)目的,數(shù)據(jù)按照文件和目錄的方式組織,文件和目錄保存在各種類(lèi)型的文件系統(tǒng)上。
XNU的BSD層負(fù)責(zé)文件系統(tǒng)的實(shí)現(xiàn),BSD 文件系統(tǒng)使用了一個(gè)名為虛擬文件系統(tǒng)交互(VFS)的框架。這個(gè)框架成為了UNIX 中內(nèi)核和各種文件系統(tǒng)實(shí)現(xiàn)(本地文件系統(tǒng)和各種文件系統(tǒng))之間的標(biāo)準(zhǔn)借接口。
磁盤(pán)設(shè)備和分區(qū)
OS X 和 iOS 遵循BSD 將硬盤(pán)當(dāng)做設(shè)備節(jié)點(diǎn)的命名約定。每一個(gè)磁盤(pán)都可以以塊設(shè)備的形式(/dev/disk#)或字符設(shè)備(裸設(shè)備)的形式(/dev/rdisk#)訪(fǎng)問(wèn)。通常情況下,磁盤(pán)和分區(qū)都是塊設(shè)備。系統(tǒng)通過(guò)mount(2)掛載文件系統(tǒng)時(shí)使用的是塊設(shè)備的表示方式。裸設(shè)備模式主要被一些底層程序使用,例如fsck(8)和pdisk(8),這些程序需要直接訪(fǎng)問(wèn)磁盤(pán)上的塊。
分區(qū)方案
文件系統(tǒng)并不是獨(dú)立存在的,而是存在在磁盤(pán)分區(qū)上。每一個(gè)磁盤(pán)都至少有一個(gè)分區(qū),而每一個(gè)分區(qū)都可以單獨(dú)格式化為文件系統(tǒng)。在某些情況下,可以允許一個(gè)文件系統(tǒng)跨越多個(gè)分區(qū)。分區(qū)方案(partitioning scheme)定義了磁盤(pán)的布局,邏輯地將磁盤(pán)分隔為一個(gè)或多個(gè)區(qū)域(每一個(gè)區(qū)域?yàn)橐粋€(gè)分區(qū)),每個(gè)分區(qū)中包含的是連續(xù)的扇區(qū)。通常情況下,磁盤(pán)的頭幾個(gè)扇區(qū)保存了磁盤(pán)的分區(qū)表,分區(qū)表列出了磁盤(pán)中的區(qū)域(起始扇區(qū)和扇區(qū)數(shù))以及每一個(gè)分區(qū)的文件系統(tǒng)類(lèi)型。OS X 傳統(tǒng)上支持3種分區(qū)方案:
- 主引導(dǎo)記錄(Master Boot Record,MBR)分區(qū):MBR 是PC XT 和 AT 年代遺留下來(lái)的產(chǎn)物,現(xiàn)在依然廣泛使用。這個(gè)分區(qū)方案依賴(lài)于 BIOS,局限性非常大,最多允許4個(gè)主分區(qū),而且是32位的(最多支持約40億個(gè)扇區(qū)),但是這個(gè)分區(qū)方案的優(yōu)點(diǎn)在于所有的操作系統(tǒng)都支持這個(gè)方案
- Apple Partition Map:這個(gè)蘋(píng)果獨(dú)有的自定義分區(qū)方案。最初流行于基于PPC的Mac,這個(gè)分區(qū)方案也是32位的,而且是蘋(píng)果私有的?,F(xiàn)在這個(gè)方案基本上被下一個(gè)方案GPT替代了,但是在一些iPod 設(shè)備(例如Classic 和 Nano)上仍然使用
- GUID分區(qū)表(GUID Partition Table,GPT):這是一個(gè)64位的方案,可管理的磁盤(pán)大小超越了千兆兆字節(jié),解決了所有最大分區(qū)的限制。這一點(diǎn)非常重要:MBR 和 APT 都是32位的,因此最大可尋址 232 個(gè)扇區(qū)。標(biāo)準(zhǔn)扇區(qū)大小為512字節(jié),因此磁盤(pán)大小最大允許為2TB。而蘋(píng)果的默認(rèn)分區(qū)方案現(xiàn)在轉(zhuǎn)移到64位架構(gòu)。GPT 也是EFI標(biāo)準(zhǔn)的一部分,因此在蘋(píng)果基于EFI的Intel硬件上可以工作得很好。
通用文件系統(tǒng)的概念
盡管不同的文件系統(tǒng)會(huì)采用完全不同的方式管理磁盤(pán)上的文件,但是所有的文件系統(tǒng)基本上都提供了同樣的原語(yǔ)。內(nèi)核對(duì)文件的接口稱(chēng)為虛擬文件系統(tǒng)交換(Virtual FileSystem Switch, VFS),VFS 就是基于這些概念構(gòu)建的。
文件
文件系統(tǒng)中最基本的概念就是文件。文件是在底層媒體(磁盤(pán)、CD-ROM或其他設(shè)備)上的一組或多組塊。在理想情況下,文件一改是單獨(dú)一組連續(xù)的塊。然而在大部分情況下,文件會(huì)占用多個(gè)塊的范圍。這些范圍成為extent。HFS+ 還定義了clump的概念,clump 表示當(dāng)前一個(gè)文件被分配或擴(kuò)張時(shí)提供的默認(rèn)分配的塊。
盡管會(huì)有碎片化,但是文件系統(tǒng)必須將文件表現(xiàn)為連續(xù)的、可自由尋址(隨機(jī)訪(fǎng)問(wèn))的區(qū)域。事實(shí)上,有一些文件系統(tǒng)就是完全虛擬的(例如Linux的/proc),還有一些是通過(guò)網(wǎng)絡(luò)映射的(例如 NFS 和 AFS)。文件請(qǐng)求者只得到一個(gè)文件描述符(通過(guò)open(2)返回的整形fd,或是通過(guò)fopen(3)返回的FILE *指針),將文件描述符當(dāng)成一個(gè)不透明的句柄。內(nèi)核在提供文件請(qǐng)求服務(wù)時(shí),需要將這個(gè)句柄轉(zhuǎn)換為文件系統(tǒng)中的標(biāo)識(shí)符。
擴(kuò)展屬性
擴(kuò)展屬性指的是用戶(hù)(或系統(tǒng))定義的屬性,可以包含應(yīng)用程序所需要的信息,在很多情況下實(shí)際包含了系統(tǒng)本身所需要的信息。Darwin 中通過(guò)擴(kuò)展屬性支持很多高級(jí)特性,例如透明的壓縮和fork,還支持訪(fǎng)問(wèn)控制列表(Access Control List)
權(quán)限
并不是所有的文件都是平等的。有一些文件包含敏感信息,因此每一個(gè)嚴(yán)肅的文件系統(tǒng)(除了 FAT 系列的文件系統(tǒng))都必須支持權(quán)限。UNIX 的文件系統(tǒng)(Mac 原生的HFS+文件系統(tǒng)也屬于一種UNIX 文件系統(tǒng))支持傳統(tǒng)的用戶(hù)/組/其他的讀/寫(xiě)/執(zhí)行的權(quán)限模型。從OS X 10.4 開(kāi)始,VFS 開(kāi)始支持更精細(xì)的權(quán)限:Access Control List(ASL,訪(fǎng)問(wèn)控制列表),OS X 允許通過(guò)chmod(1) 設(shè)置和修改ACL。通過(guò)ls(1) -e 可以顯示訪(fǎng)問(wèn)控制列表。在ls(1) -l 的輸出列表中,帶有ACL的文件會(huì)帶有一個(gè)加號(hào)(+)標(biāo)記。VFS 通過(guò)擴(kuò)展屬性支持ACL,而ACL的實(shí)施是通過(guò)一個(gè)獨(dú)立的機(jī)制KAUTH完成的。
時(shí)間戳
文件系統(tǒng)需要為其包含的文件記錄時(shí)間戳。UNIX 要求維護(hù)三個(gè)時(shí)間戳:創(chuàng)建時(shí)間、修改時(shí)間和訪(fǎng)問(wèn)時(shí)間。touch(1)命令的-acm 選項(xiàng)就對(duì)應(yīng)了這3個(gè)時(shí)間戳。ls(1) 命令的-u 參數(shù)能顯示訪(fǎng)問(wèn)時(shí)間,-U 參數(shù)顯示創(chuàng)建時(shí)間,如果不提供參數(shù)則顯示修改時(shí)間。
快捷方式和連接
大部分UNIX用戶(hù)都對(duì)連接(link)的概念很熟悉,其中既包括軟連接(也稱(chēng)為符號(hào)連接)也包括硬鏈接。軟連接是通過(guò)ln(1) -s 創(chuàng)建的,硬連接則是通過(guò)不帶-s參數(shù)的ln(1)創(chuàng)建的。從VFS 角度看,軟連接是一個(gè)不同的文件(即另一個(gè)inode,類(lèi)型為 1,包含其指向的文件的文件名。而硬連接則是目錄中的另一個(gè)條目,指向同一個(gè)底層的文件(從VFS角度看,是同一個(gè)inode)。通過(guò)另一種方式描述,可以說(shuō)硬連接存在于目錄層次,而軟連接存在于文件層次。
硬連接和軟連接一樣,都提供了一種文件快捷方式的機(jī)制。但是和軟連接的不同之處在于,硬連接可以防止誤刪文件,因?yàn)橹挥凶詈笠粋€(gè)指向文件的連接被刪除了,文件系統(tǒng)才會(huì)刪除文件。下表是硬連接和軟連接的比較:
| 軟連接 | 硬連接
---|---|---
inode|指向不同inode的不同目錄項(xiàng)(dentry)包含文件名|指向同一個(gè)inode的不同dentry
作用范圍|跨越文件系統(tǒng)|同一個(gè)文件系統(tǒng)
目錄|可連接|規(guī)定不可連接(除了 “.”和“..”之外)。實(shí)際中取決于具體實(shí)現(xiàn)
目標(biāo) rm/mv|軟連接被破壞|硬連接依然存在
目標(biāo)重新創(chuàng)建|軟連接被修復(fù)|硬連接指向“舊”的文件
查找|find - L -samefile <target>|find -samefile <target>
find -inum <targetinodenum>
蘋(píng)果生態(tài)圈中的文件系統(tǒng)
OS X 和 iOS 都支持各種各樣的文件系統(tǒng)。實(shí)際上由于內(nèi)核的模塊化設(shè)計(jì),內(nèi)核可以支持任意種類(lèi)的文件系統(tǒng),只要求系統(tǒng)服從內(nèi)核VFS標(biāo)準(zhǔn)即可。
蘋(píng)果原生的文件系統(tǒng)
- 層次文件系統(tǒng)(HFS):蘋(píng)果在Mac OS 早期時(shí)開(kāi)發(fā)的原生文件系統(tǒng)結(jié)構(gòu)
- 層次文件系統(tǒng) Plus(HFS+):用來(lái)替代HFS。HFS+ 對(duì) HFS 增加了很多擴(kuò)展以克服HFS的各種局限性
DOS/Windows 文件系統(tǒng)
- 文件分配表(FAT):最簡(jiǎn)單最原始的文件系統(tǒng),最流行的FAT-32仍然局限于2TB的卷
- NT 文件系統(tǒng)(NTFS):FAT 缺少的主要功能是權(quán)限和限額。權(quán)限系統(tǒng)的作用是支持文件的選擇性訪(fǎng)問(wèn)控制。限額機(jī)制的作用是防止用戶(hù)創(chuàng)建過(guò)多文件導(dǎo)致共享文件系統(tǒng)的濫用,為了同時(shí)滿(mǎn)足這兩個(gè) 需求,NT 文件系統(tǒng)(NTFS)出現(xiàn)了。并且是現(xiàn)在Windows的原始文件系統(tǒng)
CD/DVD 文件系統(tǒng)
- CD 音頻文件系統(tǒng)(CDDAFS)
- CD-ROM 文件系統(tǒng)(CDFS/ISO-9660)
- 通用磁盤(pán)格式(UDF)
基于網(wǎng)絡(luò)的文件系統(tǒng)
網(wǎng)絡(luò)文件系統(tǒng)的用途是將存儲(chǔ)系統(tǒng)擴(kuò)展到本地主機(jī)之外的遠(yuǎn)程主機(jī),遠(yuǎn)程主機(jī)既可以在本地局域網(wǎng)中,也可以是通過(guò)Internet 連接的遙遠(yuǎn)主機(jī)。
- 蘋(píng)果文件傳輸協(xié)議:Apple Filing Protocol,AFP是Mac OS 8 和 9 默認(rèn)的網(wǎng)絡(luò)文件協(xié)議,當(dāng)時(shí)還稱(chēng)為 AppleShare。這是一個(gè)應(yīng)用層協(xié)議,建立在蘋(píng)果私有的AppleTalk協(xié)議之上(后來(lái)蘋(píng)果投入了TCP/IP的懷抱)。目前AFP使用TCP端口427和528
- 網(wǎng)絡(luò)文件系統(tǒng)協(xié)議:網(wǎng)絡(luò)文件系統(tǒng)(Network File Systems,NFS)一個(gè)老牌的應(yīng)用層協(xié)議
- 服務(wù)器消息塊(SMB/CIFS/SMB2)協(xié)議
- 文件傳輸協(xié)議:FTP(對(duì)應(yīng)RFC 959)是最老的互聯(lián)網(wǎng)協(xié)議之一
- Web Distribute Authoring and Versioning(WebDAV):是一個(gè)推薦的HTTP擴(kuò)展協(xié)議
偽文件系統(tǒng)
偽文件系統(tǒng)部署真正的文件系統(tǒng)。偽文件系統(tǒng)可以分為兩類(lèi)
- 內(nèi)核數(shù)據(jù)結(jié)構(gòu)和設(shè)備的文件系統(tǒng)接口:Linux 的/proc 和 /sys 文件系統(tǒng),這兩個(gè)文件系統(tǒng)提供了大量診斷數(shù)據(jù)和內(nèi)核參數(shù)。UNIX 的 /dev 文件系統(tǒng),內(nèi)核通過(guò)/dev 文件系統(tǒng)暴露了各種設(shè)備的驅(qū)動(dòng)程序
- 文件系統(tǒng)組件:這些根本不是文件系統(tǒng),但是提供了處理特殊文件類(lèi)型或特殊掛載選項(xiàng)的機(jī)制。BSD(和XNU)的deadfs、specfs、FIFOfs和unionfs都屬于這一類(lèi)
掛載文件系統(tǒng)(僅限于 OS X)
OS X 支持文件系統(tǒng)的動(dòng)態(tài)掛載和卸載,并且這種支持是通過(guò)兩種機(jī)制實(shí)現(xiàn)的:
- automount:內(nèi)核的automount 組件是 autofs.kext 內(nèi)核擴(kuò)展,autofs.text 在 VFS 中注冊(cè)了 autofs 文件系統(tǒng)。autofs.text 向用戶(hù)態(tài)暴露了/dev/autofs。為了automount 操作的成功執(zhí)行,用戶(hù)態(tài)有幾個(gè)輔助 automount 的守護(hù)程序:
- autofsd:由launchd 啟動(dòng),輔助監(jiān)聽(tīng)網(wǎng)絡(luò)配置變化通知以及對(duì)automount 的調(diào)用
- autmount:查詢(xún)/etc/auto_master 文件,請(qǐng)求特定的掛載操作,automountd 執(zhí)行實(shí)際的掛載操作
- 磁盤(pán)仲裁:磁盤(pán)仲裁框架隱藏了內(nèi)核驅(qū)動(dòng)層I/O Kit 發(fā)送消息的果餐。如果不適用磁盤(pán)仲裁框架,也可以直接從I/O Kit 注冊(cè)通知
磁盤(pán)鏡像文件
OS X 使用了磁盤(pán)鏡像(disk image),磁盤(pán)鏡像文件的后綴名為.dmg。這些文件上是一個(gè)文件中包含了整個(gè)文件系統(tǒng),通常是HFS+文件系統(tǒng)。這個(gè)文件的格式為UDIF(Universal Disk Image Format,通用磁盤(pán)鏡像格式)。雙擊DMG文件格式時(shí),OS X 的Finder 可以自動(dòng)掛載 DMG 文件(通過(guò)調(diào)用CoreServices 的 DiskImageMounter.app程序):hdiutil(1) 命令也可以?huà)燧dDMG文件。DMG文件的掛載是由DiskImages.framework框架負(fù)責(zé)完成的。這是一個(gè)私有框架。
BSD 層在vnode磁盤(pán)驅(qū)動(dòng)程序中對(duì)磁盤(pán)鏡像提供了原生的支持,通過(guò)用戶(hù)態(tài)的/usr/libexec/vndevice命令可以訪(fǎng)問(wèn)這個(gè)驅(qū)動(dòng)程序。通過(guò)這條命令可以將磁盤(pán)鏡像掛載到某個(gè)BSD /dev/vn*設(shè)備。
虛擬文件系統(tǒng)交換
和大部分UN*X 一樣, OS X 使用虛擬文件系統(tǒng)(Virtual File System,VFS)交換作為所有文件系統(tǒng)的抽象層。VFS 的基本思想是定義一套適用于所有文件系統(tǒng)的公共接口,而不管文件系統(tǒng)的具體實(shí)現(xiàn)是什么,這套文件系統(tǒng)簡(jiǎn)化為基礎(chǔ)結(jié)構(gòu):文件系統(tǒng)條目、掛載條目以及vnode(抽象的inode)。任何已知的文件系統(tǒng)都可以遵循這套接口實(shí)現(xiàn)。有了這套接口,內(nèi)核就可以像各種POSIX 文件 I/O 調(diào)用提供完全一致的接口,從而可以將多種文件系統(tǒng)無(wú)縫地整合進(jìn)同一個(gè)文件樹(shù)種。
文件系統(tǒng)條目
在內(nèi)核中,通過(guò)vfs_fsentry 結(jié)構(gòu)體數(shù)組維護(hù)文件系統(tǒng)。用過(guò)vfs_fsadd和vfs_fsremove 可以分別從內(nèi)核添加和刪除文件系統(tǒng)
掛載條目
掛載條目(mount entry)是一個(gè)結(jié)構(gòu)體mount,向用戶(hù)態(tài)只暴露了一個(gè)不透明的類(lèi)型,表示一個(gè)已掛載的文件系統(tǒng)示例。掛載條目大致對(duì)應(yīng)的是文件系統(tǒng)的超級(jí)塊。超級(jí)塊是一個(gè)描述符,其中保存了全局的文件系統(tǒng)屬性。掛載條目還保存了文件系統(tǒng)的操作。文件系統(tǒng)可以注冊(cè),但是不一定被掛載。此外,同一個(gè)文件系統(tǒng)類(lèi)型可以被掛載多次。
vnode 對(duì)象
vnode 對(duì)象建立在傳統(tǒng)的UNIX inode之上。vnode 表示一個(gè)“虛擬的inode”,其中包含從磁盤(pán)獲取文件或目錄的必要信息。vnode 結(jié)構(gòu)體中有一個(gè)重要的字段是 ubc_info 結(jié)構(gòu)體:通過(guò)這個(gè)結(jié)構(gòu)體可以在同一緩沖區(qū)緩存(unified buffer cache,UBC)中找到這個(gè) vnode 的對(duì)象消息。UBC 是 BSD 保存緩存的 vnode 數(shù)據(jù)的機(jī)制,vnode 數(shù)據(jù)是從磁盤(pán)和設(shè)備文件獲取的。ubc_info 將 vnode 和 Mach 的 memory_object_t連接在一起。每一個(gè)文件系統(tǒng)都定義了自己的內(nèi)部節(jié)點(diǎn)表示方式,但是應(yīng)該支持vnode 的基本表現(xiàn)形式,還應(yīng)該支持一組定義在 vnode 上的操作:創(chuàng)建、讀取、寫(xiě)入和刪除。
FUSE:用戶(hù)空間的文件系統(tǒng)
FUSE 的內(nèi)核態(tài)組件非常簡(jiǎn)單:注冊(cè)一個(gè)VFS(通過(guò) vfs_fsadd),并且導(dǎo)出一組/dev/fuserXX字符設(shè)備。針對(duì)這個(gè)文件系統(tǒng)實(shí)例的操作都被內(nèi)核擴(kuò)展截獲,然后序列化為一條消息發(fā)給用戶(hù)態(tài)的文件系統(tǒng)處理。
FUSE在用戶(hù)態(tài)的實(shí)現(xiàn):在fuse_operations 結(jié)構(gòu)體中填充自己的文件操作回調(diào)函數(shù),然后通過(guò)fuse_main( ) 完成其他的工作。
進(jìn)程的文件 I/O 操作
BSD proc_t 結(jié)構(gòu)體中包含了一個(gè)字段 struct filedesc *p_fd,這個(gè)字段的結(jié)構(gòu)體保存了進(jìn)程打開(kāi)的所有文件。filedesc結(jié)構(gòu)體中關(guān)鍵的字段是fd_ofiles 和 fs_ofileflags。這兩個(gè)字段表示的都是數(shù)組,用戶(hù)態(tài)的整型文件描述符就是這些數(shù)組的索引(0:stdin;1:stdout;2:stderr)。第一個(gè)數(shù)組保存了對(duì)應(yīng)描述符的文件“對(duì)象”,第二個(gè)數(shù)組保存了文件打開(kāi)傳入的標(biāo)志位。fp_lookup 函數(shù)可以根據(jù)給定的文件描述符查找fileproc。