百篇部落格系列篇.本篇為:
v65.xx 鴻蒙核心源碼分析(挂載目錄篇) | 為何檔案系統需要挂載
檔案系統相關篇為:
- v62.xx 鴻蒙核心源碼分析(檔案概念篇) | 為什麼說一切皆是檔案
- v63.xx 鴻蒙核心源碼分析(檔案系統篇) | 用圖書管理說檔案系統
- v64.xx 鴻蒙核心源碼分析(索引節點篇) | 誰是檔案系統最重要的概念
- v65.xx 鴻蒙核心源碼分析(挂載目錄篇) | 為何檔案系統需要挂載
- v66.xx 鴻蒙核心源碼分析(根檔案系統) | 先挂到
上的檔案系統/
- v67.xx 鴻蒙核心源碼分析(字元裝置篇) | 位元組為機關讀寫的裝置
- v68.xx 鴻蒙核心源碼分析(VFS篇) | 檔案系統和諧共處的基礎
- v69.xx 鴻蒙核心源碼分析(檔案句柄篇) | 你為什麼叫句柄 ?
- v70.xx 鴻蒙核心源碼分析(管道檔案篇) | 如何降低資料流動成本
關于檔案系統的介紹已經寫了三篇,但才剛剛開始,其中的 [檔案系統篇] 一定要閱讀,用生活中的場景去解釋計算機各子產品設計的原理和運作機制是整個系列篇最大的特點,計算機檔案系統相關概念是非常的多的,若不還原其本質,不跳出這些概念去看問題是很難了解它為什麼要弄這麼些東東出來讓你頭大. 反之,如果搞明白了這些概念背後的真相你想忘記它們都很難,問題是經不起追問的, 多追問幾個為什麼就會離本源越來越近.
前幾篇中追問了以下幾個問題:
- 對核心來說
真的是唯一的嗎? 答案是否定的,使用電腦的經驗告訴我們,當把電腦硬碟拆下來挂到其他電腦上時,裡面的資料一樣能通路,并沒有讓你一切重來,而inode
是存放硬碟上的,你沒有辦法讓已編好序号的inode
按你的邏輯重排,這不合理更不科學. 是以結論是inode
的全局唯一性不是不想做,而是壓根臣妾做不到啊.inode
唯一性僅限于某個檔案系統的内部.inode
- 經驗還告訴我們硬碟可以有多個分區,每個分區可以被格式化成不同的檔案系統.(例如:C槽:
,D盤NTF
,E盤FAT32
),資料可以互相拷貝,毫無障礙.不同的檔案系統是如何實作檔案遷移到呢 ? 具體實作細節是怎樣的 ?ext
如果想明白了這些問題, 就能逆向倒推為什麼要有目錄,為什麼需要挂載使用, 為什麼需要根檔案系統.一切将是水到渠成 .
先說目錄,從核心視角看目錄可不能像普通老百姓從使用者視角去看,目錄是為了屏蔽檔案系統之間的差異而設計出來的概念,也就說必須在
inode
的局部唯一性之上存在一個全局唯一性才能解決統一性問題.目錄從更大尺度上去相容并蓄各檔案系統.
那它是如何解決的呢?
-
首先各個檔案系統記錄了自己内部目錄層級關系的,這個在 檔案系統篇 | 目錄項 中已經說過了. 這種關系是絕對的但也是相對的,絕對是對内,相對是對外. 例如:
A檔案系統内部如下:
B檔案系統内部如下:├─古龍系列 inode id : 789 │ ├─小李飛刀 inode id : 56 │ ├─楚留香 inode id : 342 │ └─陸小鳳 inode id : 432 └─金庸系列 inode id : 5567 ├─倚天屠龍記 inode id : 89 ├─射雕英雄傳 inode id : 1212 └─笑傲江湖 inode id : 567843
其中├─席絹系列 : inode id : 87 │ ├─上錯花轎嫁對郎 : inode id : 89 │ ├─吻上你的心 : inode id : 789 │ └─紅袖招 : inode id : 56 └─瓊瑤系列 : inode id : 321 ├─在水一方 : inode id : 234 ├─梅花三弄 : inode id : 5678 ├─煙雨濛濛 : inode id : 987 └─還珠格格 : inode id : 23
,789
兩個檔案系統中都用到了,但它們在内部是唯一的.在A檔案系統中通過89
就能找到789
,56
,342
,并且能得到相對路徑: 古龍系列/小李飛刀,古龍系列/楚留香 .也就是說拿着432
隻要進入了本檔案系統地盤,那都不叫事,事都能給你辦的妥妥的. 那如何才能進入而且不會搞錯呢?inode
挂載目錄
答案就是: 挂載目錄,也叫挂載點,集體統一指揮的前提是需要先回歸集體.如果已經有一顆目錄樹,将你們的目錄樹挂上來形成一顆更大的樹不就統一了嗎? 例如已有:
├─小說系列 inode id : 2
│ ├─武俠小說 inode id : 13
│ ├─言情小說 inode id : 14
其實它也是個檔案系統,叫根檔案系統, 它的
inode
也是獨立的, 并且能得到相對路徑
小說系列/武俠小說
,
小說系列/武俠小說
通過兩個
mount
動作, 将它變成如下所示
├─小說系列 (根檔案系統)
├─武俠小說 (根檔案系統)
│ ├─古龍系列 (A檔案系統)
│ │ ├─小李飛刀
│ │ ├─楚留香
│ │ └─陸小鳳
│ └─金庸系列 (A檔案系統)
│ ├─倚天屠龍記
│ ├─射雕英雄傳
│ └─笑傲江湖
└─言情小說 (根檔案系統)
├─席絹系列 (B檔案系統)
│ ├─上錯花轎嫁對郎
│ ├─吻上你的心
│ └─紅袖招
└─瓊瑤系列 (B檔案系統)
├─在水一方
├─梅花三弄
├─煙雨濛濛
└─還珠格格
哦,原來整顆目錄樹是由這三個檔案系統像搭積木一樣拼接起來.而兩個檔案系統的銜接點,必然會産生一個新的概念出來, 這個概念就是 挂載點,也叫 挂載目錄
Mount
可以猜測到的是挂載點的描述結構體中必有兩個檔案系統接駁點
inode
的資訊,挂鈎和脫鈎的操作也隻屬于它專有.具體如下:
//挂載操作
struct MountOps {
int (*Mount)(struct Mount *mount, struct Vnode *vnode, const void *data);//挂載
int (*Unmount)(struct Mount *mount, struct Vnode **blkdriver);//解除安裝
int (*Statfs)(struct Mount *mount, struct statfs *sbp);//統計檔案系統的資訊,如該檔案系統類型、總大小、可用大小等資訊
};
struct Mount {
LIST_ENTRY mountList; /* mount list */ //通過本節點将Mount挂到全局Mount連結清單上
const struct MountOps *ops; /* operations of mount */ //挂載操作函數
struct Vnode *vnodeBeCovered; /* vnode we mounted on */ //要被挂載的節點 即 /bin1/vs/sd 對應的 vnode節點
struct Vnode *vnodeCovered; /* syncer vnode */ //要挂載的節點 即/dev/mmcblk0p0 對應的 vnode節點
LIST_HEAD vnodeList; /* list of vnodes */ //連結清單表頭
int vnodeSize; /* size of vnode list */ //節點數量
LIST_HEAD activeVnodeList; /* list of active vnodes */ //激活的節點連結清單
int activeVnodeSize; /* szie of active vnodes list *///激活的節點數量
void *data; /* private data */ //私有資料,可使用這個成員作為一個指向它們自己内部資料的指針
uint32_t hashseed; /* Random seed for vfs hash */ //vfs 哈希随機種子
unsigned long mountFlags; /* Flags for mount */ //挂載标簽
char pathName[PATH_MAX]; /* path name of mount point */ //挂載點路徑名稱 /bin1/vs/sd
char devName[PATH_MAX]; /* path name of dev point */ //裝置名稱 /dev/mmcblk0p0
};
解讀
-
: 挂載點由雙向連結清單全局統一管理mountList
-
:,記錄挂到根檔案系統的哪個節點上.vnodeBeCovered
-
: 裝置也是一種檔案,也被統一管理,統一在vnodeCovered
目錄下,核心會給裝置的每個分區配置設定一個/dev
節點,一個分區對應一個檔案系統,裝置檔案後續有專門的介紹,此處不展開.vnode
-
: 指的是A/B檔案系統的節點連結清單,由挂載點結構體記錄.vnodeList
-
:activeVnodeList
檔案系統節點的使用情況,統一由雙向連結清單管理.A
-
:activeVnodeSize
檔案系統已被使用的節點數A
-
這是檔案系統的私有資料,跟 索引節點篇 | Vnode -> data 一樣了解.data
-
:這個很重要,記錄了pathName
,因為檔案的絕對路徑是拼接起來的,以小說系列/武俠小說
這個完整的路徑來說,它是由小說系列/武俠小說/古龍系列/小李飛刀
(根檔案系統提供) +小說系列/武俠小說
(A檔案系統提供) 這兩部分拼成的.古龍系列/小李飛刀
-
:一般名稱類似于devName
=mmcblk0p0
+mmc
+block0
Partition0
-
:mmc
可了解為硬碟MultiMediaCard
-
: 0号塊裝置block0
-
:0号分區,一個分區上安裝一個檔案系統.Partition
-
-
: 每個檔案系統挂載方式是不用的,都需要實作這幾個接口(挂載,解除安裝,統計).MountOps ops
// 檔案系統 proc 對 MountOps 接口實作 const struct MountOps procfs_operations = { .Mount = VfsProcfsMount,//裝載 .Unmount = NULL, .Statfs = VfsProcfsStatfs,//統計資訊 }; //檔案系統 fat 對MountOps 接口實作 struct MountOps fatfs_mops = { .Mount = fatfs_mount, .Unmount = fatfs_umount, .Statfs = fatfs_statfs, }; //檔案系統 jffs 對MountOps 接口實作 const struct MountOps jffs_operations = { .Mount = VfsJffs2Bind, .Unmount = VfsJffs2Unbind, .Statfs = VfsJffs2Statfs, };
問題
上面提到 挂載就需要一個已經存在的檔案系統提供目錄,也就是根檔案系統,但根檔案系統又是怎麼來的呢?
百篇部落格分析.深挖核心地基
給鴻蒙核心源碼加注釋過程中,整理出以下文章。内容立足源碼,常以生活場景打比方盡可能多的将核心知識點置入某種場景,具有畫面感,容易了解記憶。說别人能聽得懂的話很重要! 百篇部落格絕不是百度教條式的在說一堆诘屈聱牙的概念,那沒什麼意思。更希望讓核心變得栩栩如生,倍感親切.确實有難度,自不量力,但已經出發,回頭已是不可能的了。 😛
與代碼有bug需不斷debug一樣,文章和注解内容會存在不少錯漏之處,請多包涵,但會反複修正,持續更新,
.xx
代表修改的次數,精雕細琢,言簡意赅,力求打造精品内容。
編譯建構 | 基礎工具 | 加載運作 | 程序管理 |
---|---|---|---|
編譯環境篇 編譯過程篇 環境腳本篇 建構工具篇 gn應用篇 忍者ninja篇 | 雙向連結清單篇 位圖管理篇 用棧方式篇 定時器篇 原子操作篇 時間管理篇 | ELF格式篇 ELF解析篇 靜态連結篇 重定位篇 程序映像篇 | 程序管理篇 程序概念篇 Fork篇 特殊程序篇 程序回收篇 信号生産篇 信号消費篇 Shell編輯篇 Shell解析篇 |
程序通訊 | 記憶體管理 | 前因後果 | 任務管理 |
自旋鎖篇 互斥鎖篇 程序通訊篇 信号量篇 事件控制篇 消息隊列篇 | 記憶體配置設定篇 記憶體管理篇 記憶體彙編篇 記憶體映射篇 記憶體規則篇 實體記憶體篇 | 總目錄 排程故事篇 記憶體主奴篇 源碼注釋篇 源碼結構篇 靜态站點篇 | 時鐘任務篇 任務排程篇 任務管理篇 排程隊列篇 排程機制篇 線程概念篇 并發并行篇 系統調用篇 任務切換篇 |
檔案系統 | 硬體架構 | ||
檔案概念篇 檔案系統篇 索引節點篇 挂載目錄篇 根檔案系統 字元裝置篇 VFS篇 檔案句柄篇 管道檔案篇 | 彙編基礎篇 彙編傳參篇 工作模式篇 寄存器篇 異常接管篇 彙編彙總篇 中斷切換篇 中斷概念篇 中斷管理篇 |