解析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所示: