文件系統(tǒng)和虛擬文件系統(tǒng)交換
內(nèi)核的一個(gè)重要職責(zé)就是管理數(shù)據(jù)理张,這些數(shù)據(jù)既包括用戶數(shù)據(jù)也包括系統(tǒng)數(shù)據(jù)。為了實(shí)現(xiàn)這個(gè)目的授翻,數(shù)據(jù)按照文件和目錄的方式組織贯莺,文件和目錄保存在各種類型的文件系統(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)借接口。
磁盤設(shè)備和分區(qū)
OS X 和 iOS 遵循BSD 將硬盤當(dāng)做設(shè)備節(jié)點(diǎn)的命名約定唆铐。每一個(gè)磁盤都可以以塊設(shè)備的形式(/dev/disk#)或字符設(shè)備(裸設(shè)備)的形式(/dev/rdisk#)訪問哲戚。通常情況下,磁盤和分區(qū)都是塊設(shè)備艾岂。系統(tǒng)通過mount(2)掛載文件系統(tǒng)時(shí)使用的是塊設(shè)備的表示方式顺少。裸設(shè)備模式主要被一些底層程序使用,例如fsck(8)和pdisk(8)王浴,這些程序需要直接訪問磁盤上的塊脆炎。
分區(qū)方案
文件系統(tǒng)并不是獨(dú)立存在的,而是存在在磁盤分區(qū)上氓辣。每一個(gè)磁盤都至少有一個(gè)分區(qū)秒裕,而每一個(gè)分區(qū)都可以單獨(dú)格式化為文件系統(tǒng)。在某些情況下钞啸,可以允許一個(gè)文件系統(tǒng)跨越多個(gè)分區(qū)几蜻。分區(qū)方案(partitioning scheme)定義了磁盤的布局,邏輯地將磁盤分隔為一個(gè)或多個(gè)區(qū)域(每一個(gè)區(qū)域?yàn)橐粋€(gè)分區(qū))爽撒,每個(gè)分區(qū)中包含的是連續(xù)的扇區(qū)入蛆。通常情況下响蓉,磁盤的頭幾個(gè)扇區(qū)保存了磁盤的分區(qū)表硕勿,分區(qū)表列出了磁盤中的區(qū)域(起始扇區(qū)和扇區(qū)數(shù))以及每一個(gè)分區(qū)的文件系統(tǒng)類型。OS X 傳統(tǒng)上支持3種分區(qū)方案:
- 主引導(dǎo)記錄(Master Boot Record枫甲,MBR)分區(qū):MBR 是PC XT 和 AT 年代遺留下來的產(chǎn)物源武,現(xiàn)在依然廣泛使用。這個(gè)分區(qū)方案依賴于 BIOS想幻,局限性非常大粱栖,最多允許4個(gè)主分區(qū),而且是32位的(最多支持約40億個(gè)扇區(qū))脏毯,但是這個(gè)分區(qū)方案的優(yōu)點(diǎn)在于所有的操作系統(tǒng)都支持這個(gè)方案
- Apple Partition Map:這個(gè)蘋果獨(dú)有的自定義分區(qū)方案闹究。最初流行于基于PPC的Mac,這個(gè)分區(qū)方案也是32位的食店,而且是蘋果私有的≡伲現(xiàn)在這個(gè)方案基本上被下一個(gè)方案GPT替代了,但是在一些iPod 設(shè)備(例如Classic 和 Nano)上仍然使用
- GUID分區(qū)表(GUID Partition Table吉嫩,GPT):這是一個(gè)64位的方案价认,可管理的磁盤大小超越了千兆兆字節(jié),解決了所有最大分區(qū)的限制自娩。這一點(diǎn)非常重要:MBR 和 APT 都是32位的用踩,因此最大可尋址 232 個(gè)扇區(qū)。標(biāo)準(zhǔn)扇區(qū)大小為512字節(jié),因此磁盤大小最大允許為2TB脐彩。而蘋果的默認(rèn)分區(qū)方案現(xiàn)在轉(zhuǎn)移到64位架構(gòu)碎乃。GPT 也是EFI標(biāo)準(zhǔn)的一部分,因此在蘋果基于EFI的Intel硬件上可以工作得很好惠奸。
通用文件系統(tǒng)的概念
盡管不同的文件系統(tǒng)會采用完全不同的方式管理磁盤上的文件荠锭,但是所有的文件系統(tǒng)基本上都提供了同樣的原語。內(nèi)核對文件的接口稱為虛擬文件系統(tǒng)交換(Virtual FileSystem Switch, VFS)晨川,VFS 就是基于這些概念構(gòu)建的证九。
文件
文件系統(tǒng)中最基本的概念就是文件。文件是在底層媒體(磁盤共虑、CD-ROM或其他設(shè)備)上的一組或多組塊愧怜。在理想情況下,文件一改是單獨(dú)一組連續(xù)的塊妈拌。然而在大部分情況下拥坛,文件會占用多個(gè)塊的范圍。這些范圍成為extent尘分。HFS+ 還定義了clump的概念猜惋,clump 表示當(dāng)前一個(gè)文件被分配或擴(kuò)張時(shí)提供的默認(rèn)分配的塊。
盡管會有碎片化培愁,但是文件系統(tǒng)必須將文件表現(xiàn)為連續(xù)的著摔、可自由尋址(隨機(jī)訪問)的區(qū)域。事實(shí)上定续,有一些文件系統(tǒng)就是完全虛擬的(例如Linux的/proc)谍咆,還有一些是通過網(wǎng)絡(luò)映射的(例如 NFS 和 AFS)。文件請求者只得到一個(gè)文件描述符(通過open(2)返回的整形fd私股,或是通過fopen(3)返回的FILE *指針)摹察,將文件描述符當(dāng)成一個(gè)不透明的句柄。內(nèi)核在提供文件請求服務(wù)時(shí)倡鲸,需要將這個(gè)句柄轉(zhuǎn)換為文件系統(tǒng)中的標(biāo)識符供嚎。
擴(kuò)展屬性
擴(kuò)展屬性指的是用戶(或系統(tǒng))定義的屬性,可以包含應(yīng)用程序所需要的信息峭状,在很多情況下實(shí)際包含了系統(tǒng)本身所需要的信息克滴。Darwin 中通過擴(kuò)展屬性支持很多高級特性,例如透明的壓縮和fork宁炫,還支持訪問控制列表(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)的用戶/組/其他的讀/寫/執(zhí)行的權(quán)限模型望忆。從OS X 10.4 開始罩阵,VFS 開始支持更精細(xì)的權(quán)限:Access Control List(ASL,訪問控制列表)启摄,OS X 允許通過chmod(1) 設(shè)置和修改ACL稿壁。通過ls(1) -e 可以顯示訪問控制列表。在ls(1) -l 的輸出列表中歉备,帶有ACL的文件會帶有一個(gè)加號(+)標(biāo)記傅是。VFS 通過擴(kuò)展屬性支持ACL,而ACL的實(shí)施是通過一個(gè)獨(dú)立的機(jī)制KAUTH完成的蕾羊。
時(shí)間戳
文件系統(tǒng)需要為其包含的文件記錄時(shí)間戳喧笔。UNIX 要求維護(hù)三個(gè)時(shí)間戳:創(chuàng)建時(shí)間、修改時(shí)間和訪問時(shí)間龟再。touch(1)命令的-acm 選項(xiàng)就對應(yīng)了這3個(gè)時(shí)間戳书闸。ls(1) 命令的-u 參數(shù)能顯示訪問時(shí)間,-U 參數(shù)顯示創(chuàng)建時(shí)間利凑,如果不提供參數(shù)則顯示修改時(shí)間浆劲。
快捷方式和連接
大部分UNIX用戶都對連接(link)的概念很熟悉,其中既包括軟連接(也稱為符號連接)也包括硬鏈接哀澈。軟連接是通過ln(1) -s 創(chuàng)建的牌借,硬連接則是通過不帶-s參數(shù)的ln(1)創(chuàng)建的。從VFS 角度看割按,軟連接是一個(gè)不同的文件(即另一個(gè)inode膨报,類型為 1,包含其指向的文件的文件名哲虾。而硬連接則是目錄中的另一個(gè)條目丙躏,指向同一個(gè)底層的文件(從VFS角度看,是同一個(gè)inode)束凑。通過另一種方式描述,可以說硬連接存在于目錄層次栅盲,而軟連接存在于文件層次汪诉。
硬連接和軟連接一樣,都提供了一種文件快捷方式的機(jī)制谈秫。但是和軟連接的不同之處在于扒寄,硬連接可以防止誤刪文件,因?yàn)橹挥凶詈笠粋€(gè)指向文件的連接被刪除了拟烫,文件系統(tǒng)才會刪除文件该编。下表是硬連接和軟連接的比較:
| 軟連接 | 硬連接
---|---|---
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>
蘋果生態(tài)圈中的文件系統(tǒng)
OS X 和 iOS 都支持各種各樣的文件系統(tǒng)硕淑。實(shí)際上由于內(nèi)核的模塊化設(shè)計(jì)课竣,內(nèi)核可以支持任意種類的文件系統(tǒng)嘉赎,只要求系統(tǒng)服從內(nèi)核VFS標(biāo)準(zhǔn)即可。
蘋果原生的文件系統(tǒng)
- 層次文件系統(tǒng)(HFS):蘋果在Mac OS 早期時(shí)開發(fā)的原生文件系統(tǒng)結(jié)構(gòu)
- 層次文件系統(tǒng) Plus(HFS+):用來替代HFS于樟。HFS+ 對 HFS 增加了很多擴(kuò)展以克服HFS的各種局限性
DOS/Windows 文件系統(tǒng)
- 文件分配表(FAT):最簡單最原始的文件系統(tǒng)公条,最流行的FAT-32仍然局限于2TB的卷
- NT 文件系統(tǒng)(NTFS):FAT 缺少的主要功能是權(quán)限和限額。權(quán)限系統(tǒng)的作用是支持文件的選擇性訪問控制迂曲。限額機(jī)制的作用是防止用戶創(chuàng)建過多文件導(dǎo)致共享文件系統(tǒng)的濫用靶橱,為了同時(shí)滿足這兩個(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)
- 通用磁盤格式(UDF)
基于網(wǎng)絡(luò)的文件系統(tǒng)
網(wǎng)絡(luò)文件系統(tǒng)的用途是將存儲系統(tǒng)擴(kuò)展到本地主機(jī)之外的遠(yuǎn)程主機(jī)关霸,遠(yuǎn)程主機(jī)既可以在本地局域網(wǎng)中,也可以是通過Internet 連接的遙遠(yuǎn)主機(jī)杰扫。
- 蘋果文件傳輸協(xié)議:Apple Filing Protocol谒拴,AFP是Mac OS 8 和 9 默認(rèn)的網(wǎng)絡(luò)文件協(xié)議,當(dāng)時(shí)還稱為 AppleShare涉波。這是一個(gè)應(yīng)用層協(xié)議英上,建立在蘋果私有的AppleTalk協(xié)議之上(后來蘋果投入了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(對應(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)可以分為兩類
- 內(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)核通過/dev 文件系統(tǒng)暴露了各種設(shè)備的驅(qū)動程序
- 文件系統(tǒng)組件:這些根本不是文件系統(tǒng),但是提供了處理特殊文件類型或特殊掛載選項(xiàng)的機(jī)制笨觅。BSD(和XNU)的deadfs拦耐、specfs、FIFOfs和unionfs都屬于這一類
掛載文件系統(tǒng)(僅限于 OS X)
OS X 支持文件系統(tǒng)的動態(tài)掛載和卸載见剩,并且這種支持是通過兩種機(jī)制實(shí)現(xiàn)的:
- automount:內(nèi)核的automount 組件是 autofs.kext 內(nèi)核擴(kuò)展杀糯,autofs.text 在 VFS 中注冊了 autofs 文件系統(tǒng)。autofs.text 向用戶態(tài)暴露了/dev/autofs苍苞。為了automount 操作的成功執(zhí)行固翰,用戶態(tài)有幾個(gè)輔助 automount 的守護(hù)程序:
- autofsd:由launchd 啟動,輔助監(jiān)聽網(wǎng)絡(luò)配置變化通知以及對automount 的調(diào)用
- autmount:查詢/etc/auto_master 文件羹呵,請求特定的掛載操作骂际,automountd 執(zhí)行實(shí)際的掛載操作
- 磁盤仲裁:磁盤仲裁框架隱藏了內(nèi)核驅(qū)動層I/O Kit 發(fā)送消息的果餐。如果不適用磁盤仲裁框架冈欢,也可以直接從I/O Kit 注冊通知
磁盤鏡像文件
OS X 使用了磁盤鏡像(disk image)歉铝,磁盤鏡像文件的后綴名為.dmg。這些文件上是一個(gè)文件中包含了整個(gè)文件系統(tǒng)凑耻,通常是HFS+文件系統(tǒng)太示。這個(gè)文件的格式為UDIF(Universal Disk Image Format柠贤,通用磁盤鏡像格式)。雙擊DMG文件格式時(shí)先匪,OS X 的Finder 可以自動掛載 DMG 文件(通過調(diào)用CoreServices 的 DiskImageMounter.app程序):hdiutil(1) 命令也可以掛載DMG文件种吸。DMG文件的掛載是由DiskImages.framework框架負(fù)責(zé)完成的。這是一個(gè)私有框架呀非。
BSD 層在vnode磁盤驅(qū)動程序中對磁盤鏡像提供了原生的支持坚俗,通過用戶態(tài)的/usr/libexec/vndevice命令可以訪問這個(gè)驅(qū)動程序。通過這條命令可以將磁盤鏡像掛載到某個(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)簡化為基礎(chǔ)結(jié)構(gòu):文件系統(tǒng)條目剧董、掛載條目以及vnode(抽象的inode)幢尚。任何已知的文件系統(tǒng)都可以遵循這套接口實(shí)現(xiàn)。有了這套接口翅楼,內(nèi)核就可以像各種POSIX 文件 I/O 調(diào)用提供完全一致的接口尉剩,從而可以將多種文件系統(tǒng)無縫地整合進(jìn)同一個(gè)文件樹種。
文件系統(tǒng)條目
在內(nèi)核中毅臊,通過vfs_fsentry 結(jié)構(gòu)體數(shù)組維護(hù)文件系統(tǒng)理茎。用過vfs_fsadd和vfs_fsremove 可以分別從內(nèi)核添加和刪除文件系統(tǒng)
掛載條目
掛載條目(mount entry)是一個(gè)結(jié)構(gòu)體mount,向用戶態(tài)只暴露了一個(gè)不透明的類型管嬉,表示一個(gè)已掛載的文件系統(tǒng)示例皂林。掛載條目大致對應(yīng)的是文件系統(tǒng)的超級塊。超級塊是一個(gè)描述符蚯撩,其中保存了全局的文件系統(tǒng)屬性础倍。掛載條目還保存了文件系統(tǒng)的操作。文件系統(tǒng)可以注冊求厕,但是不一定被掛載著隆。此外,同一個(gè)文件系統(tǒng)類型可以被掛載多次呀癣。
vnode 對象
vnode 對象建立在傳統(tǒng)的UNIX inode之上。vnode 表示一個(gè)“虛擬的inode”弦赖,其中包含從磁盤獲取文件或目錄的必要信息项栏。vnode 結(jié)構(gòu)體中有一個(gè)重要的字段是 ubc_info 結(jié)構(gòu)體:通過這個(gè)結(jié)構(gòu)體可以在同一緩沖區(qū)緩存(unified buffer cache,UBC)中找到這個(gè) vnode 的對象消息蹬竖。UBC 是 BSD 保存緩存的 vnode 數(shù)據(jù)的機(jī)制沼沈,vnode 數(shù)據(jù)是從磁盤和設(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)建、讀取页衙、寫入和刪除摊滔。
FUSE:用戶空間的文件系統(tǒng)
FUSE 的內(nèi)核態(tài)組件非常簡單:注冊一個(gè)VFS(通過 vfs_fsadd),并且導(dǎo)出一組/dev/fuserXX字符設(shè)備店乐。針對這個(gè)文件系統(tǒng)實(shí)例的操作都被內(nèi)核擴(kuò)展截獲艰躺,然后序列化為一條消息發(fā)給用戶態(tài)的文件系統(tǒng)處理。
FUSE在用戶態(tài)的實(shí)現(xiàn):在fuse_operations 結(jié)構(gòu)體中填充自己的文件操作回調(diào)函數(shù)眨八,然后通過fuse_main( ) 完成其他的工作腺兴。
進(jìn)程的文件 I/O 操作
BSD proc_t 結(jié)構(gòu)體中包含了一個(gè)字段 struct filedesc *p_fd,這個(gè)字段的結(jié)構(gòu)體保存了進(jìn)程打開的所有文件廉侧。filedesc結(jié)構(gòu)體中關(guān)鍵的字段是fd_ofiles 和 fs_ofileflags页响。這兩個(gè)字段表示的都是數(shù)組,用戶態(tài)的整型文件描述符就是這些數(shù)組的索引(0:stdin段誊;1:stdout闰蚕;2:stderr)。第一個(gè)數(shù)組保存了對應(yīng)描述符的文件“對象”枕扫,第二個(gè)數(shù)組保存了文件打開傳入的標(biāo)志位陪腌。fp_lookup 函數(shù)可以根據(jù)給定的文件描述符查找fileproc。