百篇部落格系列篇.本篇為:
v64.xx 鴻蒙核心源碼分析(索引節點篇) | 誰是檔案系統最重要的概念 | 51 .c .h .o
檔案系統相關篇為:
- v62.xx 鴻蒙核心源碼分析(檔案概念篇) | 為什麼說一切皆是檔案 | 51 .c .h .o
- v63.xx 鴻蒙核心源碼分析(檔案系統篇) | 用圖書管理說檔案系統 | 51 .c .h .o
讀懂鴻蒙核心的關鍵線索是
LOS_DL_LIST
(雙向連結清單),它是系列篇開篇的内容.
而讀懂檔案系統的關鍵線索是
vnode
(索引節點),
vnode
在檔案系統中起承上啟下的關鍵點.
vnode
是
BSD
的叫法,鴻蒙沿用了
BSD
的稱呼,
linux
的叫法是
inode
,關于
vnode
有翻譯成虛拟節點,但系列篇還是統一翻譯成索引節點.
什麼是 vnode
先看大佬們對其的定義
OpenBSD 定義
A vnode is an object in kernel memory that speaks the UNIX file interface (open, read, write, close, readdir, etc.). Vnodes can represent files, directories, FIFOs, domain sockets, block devices, character devices.
vnode 是核心記憶體中的一個對象,它使用 UNIX 檔案接口(打開、讀取、寫入、關閉、readdir 等)。 Vnodes 可以代表檔案、目錄、FIFO、域套接字、塊裝置、字元裝置。
freeBSD 定義
vnode – internal representation of a file or directory . The vnode is the focus of all file activity in UNIX. A vnode is described by struct vnode. There is a unique vnode allocated for each active file, each current directory, each mounted-on file, text file, and the root.
vnode – 檔案或目錄的内部表示. vnode 是 UNIX 中所有檔案活動的焦點。 vnode 由 struct vnode 描述。 為每個活動檔案、每個目前目錄、每個挂載檔案、文本檔案和根配置設定了一個唯一的 vnode。
linux 定義
The inode (index node) is a data structure in a Unix-style file system that describes a file-system object such as a file or a directory. Each inode stores the attributes and disk block locations of the object’s data.[1] File-system object attributes may include metadata (times of last change, access, modification), as well as owner and permission data.
inode(索引節點)是 Unix 風格的檔案系統中的一種資料結構,用于描述檔案系統對象,例如檔案或目錄。 每個 inode 存儲對象資料的屬性和磁盤塊位置。 檔案系統對象屬性可能包括中繼資料(上次更改、通路、修改的時間),以及所有者和權限資料。
綜合所述,發現木有,這說的可不就是 v63.xx 鴻蒙核心源碼分析(檔案系統篇) | 用圖書管理說檔案系統 | 51 .c .h .o 中的索引頁嗎? 沒讀過的建議先閱讀後再繼續. 對于在硬碟中的
vnode
,在系統啟動後
vnode
會被加載到記憶體統一管理.
vnode 長啥樣
本篇主要圍繞
vnode
結構體來說,說透說爛這個檔案系統最關鍵的節點.
struct IATTR { //此結構用于記錄 vnode 的屬性
/* This structure is used for record vnode attr. */
unsigned int attr_chg_valid;//節點改變有效性 (CHG_MODE | CHG_UID | ... )
unsigned int attr_chg_flags;//額外的系統與使用者标志(flag),用來保護該檔案
unsigned attr_chg_mode; //确定了檔案的類型,以及它的所有者、它的group、其它使用者通路此檔案的權限 (S_IWUSR | ...)
unsigned attr_chg_uid; //使用者ID
unsigned attr_chg_gid; //組ID
unsigned attr_chg_size; //節點大小
unsigned attr_chg_atime; //節點最近通路時間
unsigned attr_chg_mtime; //節點對應的檔案内容被修改時間
unsigned attr_chg_ctime; //節點自身被修改時間
};
// 對IATTR的修改最終将落到 vnode->vop->Chattr(vnode, attr);
enum VnodeType {//節點類型
VNODE_TYPE_UNKNOWN, /* unknown type */ //未知類型
VNODE_TYPE_REG, /* regular file */ //vnode代表一個正則檔案(普通檔案)
VNODE_TYPE_DIR, /* directory */ //vnode代表一個目錄
VNODE_TYPE_BLK, /* block device */ //vnode代表一個塊裝置
VNODE_TYPE_CHR, /* char device */ //vnode代表一個字元裝置
VNODE_TYPE_BCHR, /* block char mix device *///塊和字元裝置混合
VNODE_TYPE_FIFO, /* pipe */ //vnode代表一個管道
VNODE_TYPE_LNK, /* link */ //vnode代表一個符号連結
};
struct Vnode {//vnode并不包含檔案名,因為 vnode和檔案名是 1:N 的關系
enum VnodeType type; /* vnode type */ //節點類型 (檔案|目錄|連結...)
int useCount; /* ref count of users *///節點引用(連結)數,即有多少檔案名指向這個vnode,即上層了解的硬連結數
uint32_t hash; /* vnode hash */ //節點哈希值
uint uid; /* uid for dac */ //檔案擁有者的User ID
uint gid; /* gid for dac */ //檔案的Group ID
mode_t mode; /* mode for dac */ //chmod 檔案的讀、寫、執行權限
LIST_HEAD parentPathCaches; /* pathCaches point to parents */ //指向父級路徑緩存,上面的都是當了爸爸節點
LIST_HEAD childPathCaches; /* pathCaches point to children */ //指向子級路徑緩存,上面都是當了别人兒子的節點
struct Vnode *parent; /* parent vnode */ //父節點
struct VnodeOps *vop; /* vnode operations */ //相當于指定操作Vnode方式 (接口實作|驅動程式)
struct file_operations_vfs *fop; /* file operations */ //相當于指定檔案系統
void *data; /* private data */ //檔案資料block的位置,指向每種具體裝置私有的成員,例如 ( drv_data | nfsnode | ....)
uint32_t flag; /* vnode flag */ //節點标簽
LIST_ENTRY hashEntry; /* list entry for bucket in hash table */ //通過它挂入哈希表 g_vnodeHashEntrys[i], i:[0,g_vnodeHashMask]
LIST_ENTRY actFreeEntry; /* vnode active/free list entry */ //通過本節點挂到空閑連結清單和使用連結清單上
struct Mount *originMount; /* fs info about this vnode */ //自己所在的檔案系統挂載資訊
struct Mount *newMount; /* fs info about who mount on this vnode */ //其他挂載在這個節點上檔案系統資訊
};
解讀
-
即七種檔案類型,鴻蒙增加了一種VnodeType
,去掉了VNODE_TYPE_BCHR
類型,沒搞懂為什麼.socket
-
代表硬連結數,任何目錄下都會有useCount
,.
兩個檔案, 前者指向目前目錄,後者指向父目錄.這樣做的好處是由索引頁指向的資料塊中(目錄項)存有父目錄和目前目錄的索引号,有了索引号就能很快的找到對應的索引頁.例如當外部使用..
這樣的指令時,隻需在目前目錄(inode)所指向的目錄項中查找cd ../../../
的索引号.這樣是非常的快捷和友善的,用自己勤勞的雙手就能解決的困擾何必去麻煩别人呢.因為被下級留有記錄是以硬連結數會增加.會增加多少呢? 舉例說明,..
指令用于檢視索引節點資訊stat
注意[email protected]:/home/openharmony/code-v1.1.1-LTS/kernel/liteos_a$ stat kernel File: kernel Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 805h/2053d Inode: 1099218 Links: 7 Access: (0755/drwxr-xr-x) Uid: ( 1000/ turing) Gid: ( 1000/ turing)
,而Inode: 1099218
代表Links: 7
被七個地方所關聯,除了自己應該還有六個,在哪呢? 用kernel
指令展開ll -a
看看kernel
發現包括[email protected]:/home/openharmony/code-v1.1.1-LTS/kernel/liteos_a/kernel$ ll -a total 36 drwxr-xr-x 7 turing turing 4096 Jun 21 02:38 ./ drwxr-xr-x 21 turing turing 4096 Jul 23 19:45 ../ drwxr-xr-x 11 turing turing 4096 Jun 21 02:38 base/ -rwxr-xr-x 1 turing turing 2214 Jun 21 02:38 BUILD.gn* drwxr-xr-x 3 turing turing 4096 Jun 21 02:38 common/ drwxr-xr-x 9 turing turing 4096 Jun 21 02:38 extended/ drwxr-xr-x 2 turing turing 4096 Jun 21 02:38 include/ -rwxr-xr-x 1 turing turing 2864 Jun 21 02:38 Kconfig* drwxr-xr-x 4 turing turing 4096 Jun 21 02:38 user/
,.
在内有七個目錄..
代表的是目錄,但是注意其中的d
并不指向../
而是指向它的父級kernel
,其餘的liteos_a
,./
,base/..
六個剛好指向common/..
,可以驗證下它們的kernel
資訊就知道了.inode
會發現[email protected]:/home/openharmony/code-v1.1.1-LTS/kernel/liteos_a$ stat ./kernel/. File: ./kernel/. Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 805h/2053d Inode: 1099218 Links: 7 Access: (0755/drwxr-xr-x) Uid: ( 1000/ turing) Gid: ( 1000/ turing) [email protected]:/home/openharmony/code-v1.1.1-LTS/kernel/liteos_a$ stat ./kernel/base/.. File: ./kernel/base/.. Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 805h/2053d Inode: 1099218 Links: 7 Access: (0755/drwxr-xr-x) Uid: ( 1000/ turing) Gid: ( 1000/ turing) [email protected]:/home/openharmony/code-v1.1.1-LTS/kernel/liteos_a$ stat ./kernel/.. File: ./kernel/.. Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 805h/2053d Inode: 1099213 Links: 21 Access: (0755/drwxr-xr-x) Uid: ( 1000/ turing) Gid: ( 1000/ turing)
和./kernel/.
的./kernel/base/..
都是Inode
,而1099218
的為./kernel/..
是不一樣.1099213
- 正常情況下一個目錄的
,.
是不一樣的,但隻有一個目錄例外,就是..
/
其[email protected]:/$ stat /. File: /. Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 805h/2053d Inode: 2 Links: 20 [email protected]:/$ stat /.. File: /.. Size: 4096 Blocks: 8 IO Block: 4096 directory Device: 805h/2053d Inode: 2 Links: 20
結果都是一樣的,inode
,那麼問題來了,Inode: 2
為 和Inode
的節點去哪了呢?1
-
,uid
代表檔案所屬使用者/使用者組和權限.discretionary access control (DAC) 自主通路控制.在計算機安全中,自主通路控制 (DAC) 是一種由可信計算機系統評估标準定義的通路控制“作為一種根據對象所屬的主體群組的身份限制對對象的通路的手段. 控制方式是自由的,因為具有特定通路權限的主體能夠将該權限(可能是間接地)傳遞給任何其他主體(除非受到強制通路控制的限制)。與其對應的是 mandatory access control (MAC) 強制通路控制.gid``mode
-
路徑緩存連結清單,使用者快速查找父子資訊.parentPathCaches``childPathCaches
-
指向父節點,父節點不管是什麼内容,一樣都是檔案,都用parent
描述.Vnode
-
這是對VnodeOps *vop
的操作,vnode
本身也是資料,存儲在索引表中,記錄了使用者,使用者組,權限,時間等資訊,這部分資訊是可以修改的,就需要接口來維護,便是vnode
.VnodeOps
看到沒有裡面的所有方法都是對索引節點(索引頁)的增删改查操作,并不操作索引節點指向的資料塊(圖書區)内容.struct VnodeOps { int (*Create)(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode);//建立節點 int (*Lookup)(struct Vnode *parent, const char *name, int len, struct Vnode **vnode);//查詢節點 //Lookup向底層檔案系統查找擷取inode資訊 int (*Open)(struct Vnode *vnode, int fd, int mode, int flags);//打開節點 int (*Close)(struct Vnode *vnode);//關閉節點 int (*Reclaim)(struct Vnode *vnode);//回收節點 int (*Unlink)(struct Vnode *parent, struct Vnode *vnode, const char *fileName);//取消硬連結 int (*Rmdir)(struct Vnode *parent, struct Vnode *vnode, const char *dirName);//删除目錄節點 int (*Mkdir)(struct Vnode *parent, const char *dirName, mode_t mode, struct Vnode **vnode);//建立目錄節點 int (*Readdir)(struct Vnode *vnode, struct fs_dirent_s *dir);//讀目錄節點 int (*Opendir)(struct Vnode *vnode, struct fs_dirent_s *dir);//打開目錄節點 int (*Rewinddir)(struct Vnode *vnode, struct fs_dirent_s *dir);//定位目錄節點 int (*Closedir)(struct Vnode *vnode, struct fs_dirent_s *dir);//關閉目錄節點 int (*Getattr)(struct Vnode *vnode, struct stat *st);//擷取節點屬性 int (*Setattr)(struct Vnode *vnode, struct stat *st);//設定節點屬性 int (*Chattr)(struct Vnode *vnode, struct IATTR *attr);//改變節點屬性(change attr) int (*Rename)(struct Vnode *src, struct Vnode *dstParent, const char *srcName, const char *dstName);//重命名 .... }
- 那麼對資料塊(圖書區)的修改用什麼方法呢? 答案是:
,file_operations_vfs *fop
/* This structure is provided by devices when they are registered with the * system. It is used to call back to perform device specific operations. */ //該結構由裝置在向系統注冊時提供,它用于回調以執行特定于裝置的操作。 struct file_operations_vfs { /* The device driver open method differs from the mountpoint open method */ int (*open)(struct file *filep); /* The following methods must be identical in signature and position because * the struct file_operations and struct mountp_operations are treated like * unions. */ int (*close)(struct file *filep); ssize_t (*read)(struct file *filep, char *buffer, size_t buflen); ssize_t (*write)(struct file *filep, const char *buffer, size_t buflen); off_t (*seek)(struct file *filep, off_t offset, int whence); int (*ioctl)(struct file *filep, int cmd, unsigned long arg); int (*mmap)(struct file* filep, struct VmMapRegion *region); /* The two structures need not be common after this point */ .... };
看參數就知道,很是給file_operations_vfs
的上層的使用的,它是夾在應用層和vnode
中間的一層,是vnode
起承上啟下作用的上層,具體為什麼要有vnode
存在後續會詳細說明,總之通過file
找到file
,進而對vnode
指向的内容區進行修改.我們在應用層比如修改一個vnode
,建立一個ppt
文檔這些操作就是通過word
file_operations_vfs
.
一定要搞清楚
和VnodeOps
二者的差別,一個是對索引頁的操作,一個是對索引頁指向的内容的操作.file_operations_vfs
-
使用了一個data
類型,這是私有格式資料,說明運作時才知道是什麼類型,就像一個沒有任何提示資訊的私人密碼箱一樣,是打不開的,不知道順序亂開隻會毀掉資料,隻有密碼箱那邊派人來了才能開,而這人就是各種不同的檔案系統.每種檔案系統如何讀取資料的方式是不同的,差異化的就有接口内部來實作了.對外是相同的,無非都是讀讀寫寫.void
-
使用雜湊演算法來檢索hashEntry
vnode
-
:這個就不用介紹了,雙向連結清單是核心最重要的結構體,通過它挂到全局空閑連結清單和使用連結清單上.actFreeEntry
-
和originMount
是挂載相關的,任務檔案系統都需要先挂載到根檔案系統下才能使用.關于挂載後續有詳細介紹.newMount
鴻蒙核心源碼分析.總目錄
v08.xx 鴻蒙核心源碼分析(總目錄) | 百萬漢字注解 百篇部落格分析 | 51 .c .h .o
百萬漢字注解.百篇部落格分析
百萬漢字注解 >> 精讀鴻蒙源碼,中文注解分析, 深挖地基工程,大腦永久記憶,四大碼倉每日同步更新< gitee | github | csdn | coding >
百篇部落格分析 >> 故事說核心,問答式導讀,生活式比喻,表格化說明,圖形化展示,主流站點定期更新中< 51cto | csdn | harmony | osc >
關注不迷路.代碼即人生
熱愛是所有的理由和答案 - turing
原創不易,歡迎轉載,但麻煩請注明出處.