1. 程式人生 > 其它 >解析Linux中的VFS檔案系統之檔案系統的註冊(二)

解析Linux中的VFS檔案系統之檔案系統的註冊(二)

繼上一篇文章:https://cloud.tencent.com/developer/article/1053882

3. 檔案系統的註冊

這裡的檔案系統是指可能會被掛載到目錄樹中的各個實際檔案系統,所謂實際檔案系統,即是指VFS 中的實際操作最終要通過它們來完成而已,並不意味著它們一定要存在於某種特定的儲存裝置上。比如在筆者的 Linux 機器下就註冊有 "rootfs"、"proc"、"ext2"、"sockfs" 等十幾種檔案系統。

3.1 檔案系統的資料結構

在 Linux 原始碼中,每種實際的檔案系統用以下的資料結構表示(include/linux/fs.h):

 1 struct file_system_type {
 2     const char *name;
 3     int fs_flags;
 4     struct dentry *(*mount) (struct file_system_type *, int,
 5                const char *, void *);
 6     void (*kill_sb) (struct super_block *);
 7     struct module *owner;
 8     struct file_system_type * next;
 9     struct hlist_head fs_supers;
10 
11     struct lock_class_key s_lock_key;
12     struct lock_class_key s_umount_key;
13     struct lock_class_key s_vfs_rename_key;
14 
15     struct lock_class_key i_lock_key;
16     struct lock_class_key i_mutex_key;
17     struct lock_class_key i_mutex_dir_key;
18 };

註冊過程實際上將表示各實際檔案系統的 struct file_system_type 資料結構的例項化,然後形成一個連結串列,核心中用一個名為 file_systems 的全域性變數來指向該連結串列的表頭。

-------------------------------------------------------------------------------- 

name:檔案系統的名字,這個名字唯一的標識一種檔案系統;

next:為檔案系統的連結串列指標;

fs_supers:對於每一個mount的檔案系統,系統都會為它建立一個super_block資料結構,該結構儲存檔案系統本省以及掛載點相關的資訊。由於可以同時掛載多個同一檔案系統型別的檔案系統(比如/ 和/home都掛載了ext3檔案系統),因此同一個檔案系統型別會對應多個super block,@fs_supers就把這個檔案系統型別對應的super block連結起來。

owner是指向module的指標,僅當檔案系統型別是以模組方式註冊時,owner才有效。

mount:這個函式非常重要,它VFS能夠和底層檔案系統互動的起始點,該函式是不能放在super_block結構中的,因為super_block是在get_sb執行之後才能建立的。get_sb從底層檔案系統獲取super_block的資訊,是和底層檔案系統相關的。

-------------------------------------------------------------------------------- 

3.2 註冊 rootfs 檔案系統

 在眾多的實際檔案系統中,之所以單獨介紹 rootfs 檔案系統的註冊過程,實在是因為該檔案系統 VFS 的關係太過密切,如果說 ext2/ext3 是 Linux 的本土檔案系統,那麼 rootfs 檔案系統則是 VFS 存在的基礎。一般檔案系統的註冊都是通過 module_init 巨集以及 do_initcalls() 函式來完成(讀者可通過閱讀module_init 巨集的宣告及 archi386vmlinux.lds 檔案來理解這一過程),但是 rootfs 的註冊卻是通過 init_rootfs() 這一初始化函式來完成,這意味著 rootfs 的註冊過程是 Linux 核心初始化階段不可分割的一部分。

(在fs/filesystem.c中69行)

 1 int register_filesystem(struct file_system_type * fs)
 2 {
 3     int res = 0;
 4     struct file_system_type ** p;
 5 
 6     BUG_ON(strchr(fs->name, '.'));
 7     if (fs->next)
 8         return -EBUSY;
 9     write_lock(&file_systems_lock);
10     p = find_filesystem(fs->name, strlen(fs->name));
11     if (*p)
12         res = -EBUSY;
13     else
14         *p = fs;
15     write_unlock(&file_systems_lock);
16     return res;
17 }

(fs/ramfs/inode.c中270行)

 1 static int __init init_ramfs_fs(void)
 2 {
 3     return register_filesystem(&ramfs_fs_type);
 4 }
 5 module_init(init_ramfs_fs)
 6 
 7 int __init init_rootfs(void)
 8 {
 9     int err;
10 
11     err = bdi_init(&ramfs_backing_dev_info);
12     if (err)
13         return err;
14 
15     err = register_filesystem(&rootfs_fs_type);
16     if (err)
17         bdi_destroy(&ramfs_backing_dev_info);
18 
19     return err;
20 }

init_rootfs() 通過呼叫 register_filesystem(&rootfs_fs_type) 函式來完成 rootfs 檔案系統註冊的,其中rootfs_fs_type 定義如下:

1 struct file_system_type rootfs_fs_type = { 
2     name:        "rootfs", 
3     read_super:    ramfs_read_super, 
4     fs_flags:    FS_NOMOUNT|FS_LITTER, 
5     owner:        THIS_MODULE, 
6  }

註冊之後的 file_systems 連結串列結構如下圖2所示: