解析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 宏的声明及 arch\i386\vmlinux.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所示:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第三十三天 MongoDB初级学习

NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。

752
来自专栏林冠宏的技术文章

关于java连接mysql数据库的几个问题的解决方法。

今天就为了连接下数据库获取信息来提供给ListView使用,搞了足足5小时。 出现的问题有:       第一个是,DriverManager.getConne...

1766
来自专栏Charlie's Road

Python文件读写保存操作

上面的代码其实没啥要介绍的,就是一个for循环然后逻辑和单个文件读操作一样,只是多了个写操作。

561
来自专栏开发与安全

linux系统编程之基础必备(三):文件描述符file descriptor与inode的相关知识

       每个进程在Linux内核中都有一个task_struct结构体来维护进程相关的 信息,称为进程描述符(Process Descriptor),而在...

1986
来自专栏编程软文

redis的使用和安装,redis基础和高级部分

2437
来自专栏小怪聊职场

MySQL(四)|《千万级大数据查询优化》第一篇:创建高性能的索引(补充)

本文是MySQL(三)|《千万级大数据查询优化》第一篇:创建高性能的索引的一个补充。 主要包括如下几点:

952
来自专栏数据和云

innodb实例损坏情况下恢复数据及相关工具的开发

作者介绍:谢浩,现任职于云和恩墨(北京)信息技术有限公司,具有多年oracle数据库企业级运维经验,擅长结合业务、硬件系统制定各种项目方案,具有丰富mysql相...

2978
来自专栏L宝宝聊IT

存储过程和触发器的应用

1244
来自专栏Albert陈凯

批量删除文件好久不用的命令记不住存下来备查find ... -exec rm {} ;find ... | xargs rm -rffind ./ -type f -name "*.cpp"|xarg

find ... -exec rm {} ; find ... | xargs rm -rf 两者都可以把find命令查找到的结果删除, 其区别简单的说是前者是...

3275
来自专栏Java帮帮-微信公众号-技术文章全总结

【数据库】数据库优化(SQL优化)

【数据库】数据库优化(SQL优化) sql语句优化 1.查询的模糊匹配 尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分...

4174

扫码关注云+社区