Apple 自 macOS Catalina 起引入了一個新的檔案階層系統,用以區隔同一個 Apple 檔案系統(APFS)容器(Container)內的系統以及使用者資料:Macintosh HD 作為系統檔案使用並以唯讀形式掛載;Macintosh HD - Data 作為使用者互動檔案(例如:應用程式、偏好設定檔案)使用並以可讀寫形式掛載。容器中亦包含了其他像是 Recovery 這種用於系統還原(RecoveryOS)使用的磁區(Volume):
$ diskutil list
/dev/disk0 (internal, physical):
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *1.0 TB disk0
1: Apple_APFS_ISC Container disk2 524.3 MB disk0s1
2: Apple_APFS Container disk3 994.7 GB disk0s2
3: Apple_APFS_Recovery Container disk1 5.4 GB disk0s3
/dev/disk3 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +994.7 GB disk3
Physical Store disk0s2
1: APFS Volume Macintosh HD - Data 410.4 GB disk3s1
2: APFS Volume Macintosh HD 8.9 GB disk3s3
3: APFS Snapshot com.apple.os.update-... 8.9 GB disk3s3s1
4: APFS Volume Preboot 4.7 GB disk3s4
5: APFS Volume Recovery 769.9 MB disk3s5
6: APFS Volume VM 2.1 GB disk3s6
每個磁區的角色(Role)於它們的 Superblock 架構(apfs_superblock_t
)中指派,相關定義可在 Apple 官方的 APFS 參考資料中找到:
#define APFS_VOL_ROLE_NONE 0x0000
#define APFS_VOL_ROLE_SYSTEM 0x0001
#define APFS_VOL_ROLE_USER 0x0002
#define APFS_VOL_ROLE_RECOVERY 0x0004
#define APFS_VOL_ROLE_VM 0x0008
#define APFS_VOL_ROLE_PREBOOT 0x0010
#define APFS_VOL_ROLE_INSTALLER 0x0020
#define APFS_VOL_ROLE_DATA 0x0040
#define APFS_VOL_ROLE_BASEBAND 0x0080
雖然當時對於 macOS 來說這是全新的概念,但這項措施其實已經用於 iOS 一段時間。當系統啟動時,Macintosh HD(APFS_VOL_ROLE_SYSTEM
)和 Macintosh HD - Data(APFS_VOL_ROLE_DATA
)兩個磁區會顯示為單一邏輯磁區,且兩者的內容將透過 Firmlink 合併為一。
Firmlinks
Firmlink 類似於 Symbolic Link 但允許雙向移動且僅適用於目錄。這有效的使 macOS 能夠整併 Macintosh HD 及 Macintosh HD - Data 的內容,例如:位於唯讀磁區 Macintosh HD 的目錄 /Users
實際上為 Macintosh HD - Data 這個可讀寫磁區上 /Shared
目錄的 Firmlink。此項設計同時也讓 Apple’s 系統完整性保護(System Integrity Protection,SIP)能更加完美的銜接,例如:受 SIP 保護的系統應用程式安裝於唯讀目錄 /System/Applications
,而使用者應用程式則可被安裝於 /Applications
,然而使用者僅會看到兩者內容合併顯示於根目錄下的 /Applications
。
系統預設的 Firmlink 可於 /usr/share/firmlinks
中查詢:
$ cat /usr/share/firmlinks
/AppleInternal AppleInternal
/Applications Applications
/Library Library
/System/Library/Caches System/Library/Caches
/System/Library/Assets System/Library/Assets
/System/Library/PreinstalledAssets System/Library/PreinstalledAssets
/System/Library/AssetsV2 System/Library/AssetsV2
/System/Library/PreinstalledAssetsV2 System/Library/PreinstalledAssetsV2
/System/Library/CoreServices/CoreTypes.bundle/Contents/Library System/Library/CoreServices/CoreTypes.bundle/Contents/Library
/System/Library/Speech System/Library/Speech
/Users Users
/Volumes Volumes
/cores cores
/opt opt
/private private
/usr/local usr/local
/usr/libexec/cups usr/libexec/cups
/usr/share/snmp usr/share/snmp
建立你自己的合成 Firmlink
自 Catalina 起要於根目錄下建立目錄,我們必須仰賴合成 Firmlink(Synthetic Firmlink):
- 在
/etc
目錄下新增一個名為synthetic.conf
的檔案。 - 確保該檔案的權限設定如下:
root:讀,寫
wheel:讀
everyone:讀
(通常只要透過指令「sudo touch /etc/synthetic.conf
」即可完成上述設定。)
要將目錄 /Users/foo/bar
連結至 /baz
,我們可以新增一個新的條目至剛剛建立的檔案:
# create a firmlink named "baz" at / which points to "Users/foo/bar"
baz Users/foo/bar
你也可以檢視 man synthetic.conf
來查詢所有可用的選項。請注意,兩個路徑中間必須使用一個「tab」做分隔,使用空白符號將不會產生作用。同時路徑的開頭不包含反斜線(/
)。重新啟動系統後剛剛的變更即會生效。