linux下VFS

  通用文件模型由下列對象類型組成:

超級塊對象:存放已安裝文件系統的有關信息

索引節點對象:存放關於具體文件的一般信息

文件對象:存放打開文件和進程之間交互的有關信息

目錄項對象:存放目錄項與對應文件進行鏈接的有關信息

  所有的超級塊對象都以雙向循環鏈表的形式鏈接在一起。

  任何基於磁盤文件系統都需要訪問和更改自己的磁盤分配位圖,以便分配或釋放磁盤塊。

  文件系統處理文件所需要的所有信息都放在一個名爲索引節點的數據結構中。每個索引對象總是出現在這幾個雙向循環鏈表的某個鏈表中(有效未使用的索引節點鏈表,正在使用的索引節點鏈表,髒索引節點鏈表)

文件對象是在文件被打開時創建由file結構組成,文件對象在磁盤上沒有對應的映像

文件指針必須存放在文件對象而不是索引節點對象中,文件對象通過一個名爲filp的slab高速緩存分配,filp描述符地址存放在filp_cechaep(fs/file_table.c)變量中。

每個超級塊對象把文件對象鏈表的頭存放在s_file字段中,因此屬於不同文件系統的文件對象就包含在不同的鏈表中。

當VFS代表進程必須打開一個文件時,它調用get_empty_filp()函數來分配一個新的文件對象,該函數調用kmem_cache_alloc()從filp高速緩存中獲得一個空閒的文件對象。

當內核將一個索引節點從磁盤裝入內存時,就會把指向這些文件操作的指針存放在file_operation結構中,該結構的地址就存放在該索引節點的i_fop字段中。

一旦目錄項被存入內存,VFS就把它轉換成基於dentry結構的一個目錄項對象,目錄項對象在磁盤上沒有對應的映像,目錄項對象存放在名爲dentry_cache的slab分配器高速緩存中。

每個目錄項對象處於四種狀態之一:空閒狀態,未使用狀態,正在使用狀態,負狀態

  從磁盤讀入一個目錄項並構造相應的目錄項對象需要花費大量的時間,在內核內存中,並不丟棄與未用目錄相關的索引節點,這是由於目錄項高速緩存仍在使用它們。

所有“未使用”目錄項對象對存放在一個“最近最少使用LRU”的雙向鏈表中,該鏈表按照插入的時間排序。

當指向相應文件的最後一個硬鏈接被刪除之後,一個“正在使用”的目錄項對象可能變成"負"狀態。

每個進程都有它自己當前的工作目錄和它自己的根目錄。

每個進程由一個task_struct進程描述符表示,其中fs_struct代表了文件系統的信息

  struct fs_struct {
          int users;
          spinlock_t lock;
          seqcount_t seq;
          int umask;
          int in_exec;
          struct path root, pwd;
  };

files_struct代表了打開的文件的信息

  /*       
   * Open file table structure
   */      
  struct files_struct {
    /*     
     * read mostly part
     */
          atomic_t count;
          struct fdtable __rcu *fdt;
          struct fdtable fdtab;
    /*     
     * written part on a separate cache line in SMP
     */
          spinlock_t file_lock ____cacheline_aligned_in_smp;
          int next_fd;
          struct embedded_fd_set close_on_exec_init;
          struct embedded_fd_set open_fds_init;
          struct file __rcu * fd_array[NR_OPEN_DEFAULT];
  };

其中fd字段指向文件對象的指針數組,數組的索引就是文件描述符。

open_fds字段最初包含open_fds_init字段的地址,open_fds_init字段表示當前已打開文件的文件描述符的位圖

當內核開始使用一個文件對象時,內核提供fget()函數以供調用,使文件對象引用計數器f_count的值增1.

文件系統註冊通常在系統初始化期間並且在使用文件系統類型之前必須執行的基本操作。

特殊文件系統不限於物理塊設備,然而,內核給每個安裝的特殊文件系統分配一個虛擬的塊設備,讓其主設備號爲0而次設備號具有任意值。

set_anon_super()函數用於初始化特殊文件系統的超級塊,該函數本質上獲得一個未使用的次設備號dev,然後使用主設備號0和次設備號dev設置新超級塊的s_dev字段。

每個註冊文件系統都用一個類型爲file_system_type的對象來表示。

根文件系統有內核在引導階段直接安裝,並擁有系統初始化腳本以及最基本的系統程序。

通常大多數進程共享同一個命名空間,即位於系統的根文件系統且被init進程使用的已安裝文件系統樹.//???什麼意思

linux中同一個文件系統被安裝多次是可能的,不管一個文件系統被安裝了多少次,都僅有一個超級塊對象

對每一個安裝操作,內核必須在內存中保存安裝點和安裝標誌,以及要安裝文件系統和其他已安裝文件系統之間的關係,這樣的信息保存在已安裝文件系統描述符中,每個描述符是一個具有vfsmount類型的數據結構。

該版本下的sys_mount是原型爲

 SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,

                 char __user *, type, unsigned long, flags, void __user *, data)

do_mount();->do_new_mount();->do_kern_mount();->vfs_kern_mount();->mount_fs();->再調用回調函數

安裝根文件系統分爲兩個階段

1.安裝內核特殊rootfs,該文件僅提供一個作爲初始安裝點的空目錄

在mnt_init()函數中由init_rootfs()和init_mount_tree()完成

2.內核在空目錄上安裝實際根文件系統

在第二階段reset_init();中的kernel_init();調用prepare_namespace();

rootfs特殊文件系統沒有被卸載,只是隱藏在基於磁盤的根文件系統下了。

當進程必須識別一個文件時,就把它的文件路徑名傳遞給某個VFS系統調用。

VFS系統調用的實現就完全要自己一點一點耐心的去看linux內核源碼了,並不是結構和知識上的問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章