天天看點

鴻蒙核心源碼分析(索引節點篇) | 誰是檔案系統最重要的概念 | 百篇部落格分析OpenHarmony源碼 | v64.01

鴻蒙核心源碼分析(索引節點篇) | 誰是檔案系統最重要的概念 | 百篇部落格分析OpenHarmony源碼 | v64.01

百篇部落格系列篇.本篇為:

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

    代表硬連結數,任何目錄下都會有

    .

    ,

    ..

    兩個檔案, 前者指向目前目錄,後者指向父目錄.這樣做的好處是由索引頁指向的資料塊中(目錄項)存有父目錄和目前目錄的索引号,有了索引号就能很快的找到對應的索引頁.例如當外部使用

    cd ../../../

    這樣的指令時,隻需在目前目錄(inode)所指向的目錄項中查找

    ..

    的索引号.這樣是非常的快捷和友善的,用自己勤勞的雙手就能解決的困擾何必去麻煩别人呢.因為被下級留有記錄是以硬連結數會增加.會增加多少呢? 舉例說明,

    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

    ,

    gid``mode

    代表檔案所屬使用者/使用者組和權限.discretionary access control (DAC) 自主通路控制.在計算機安全中,自主通路控制 (DAC) 是一種由可信計算機系統評估标準定義的通路控制“作為一種根據對象所屬的主體群組的身份限制對對象的通路的手段. 控制方式是自由的,因為具有特定通路權限的主體能夠将該權限(可能是間接地)傳遞給任何其他主體(除非受到強制通路控制的限制)。與其對應的是 mandatory access control (MAC) 強制通路控制.
  • 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 >

關注不迷路.代碼即人生

鴻蒙核心源碼分析(索引節點篇) | 誰是檔案系統最重要的概念 | 百篇部落格分析OpenHarmony源碼 | v64.01

熱愛是所有的理由和答案 - turing

原創不易,歡迎轉載,但麻煩請注明出處.

繼續閱讀