1.概览
VFS全称为 virtual file systemfile 即虚拟文件系统,它被设计出来的目的则是为了将文件系统抽象化及标准化。抽象的过程其实就是归纳总结的过程,需要提炼出一套适用于所有文件系统的共性来,既然是适用所有文件系统的那么也就可以称之为标准了。使用虚拟文件系统可以为用户层屏蔽掉各式各样的文件系统,例如基于内存的procfs、sysfs,基于磁盘的Ext文件系统家族以及来自于微软的NTFS、VFAT,还有来自华为的EROFS等。总之一句话,抽象而出的VFS就是为了屏蔽具体不同文件系统用的。举个没有VFS的拷贝操作,
cp /nfsfs/data1 /ext4/data
如果没有VFS,那么开发cp命令的时候就需要根据不同的文件系统来调用其内部实现的拷贝方法。那么使用VFS后,不论是基于nfs的还是ext4的拷贝方法,对于cp命令开发而言都是同一个系统调用了。
2.关键概念
下面还是需要介绍下VFS中重要的几个概念的。越是抽象的东西其涵盖的内容也就越多,因此理解起来相对更难。所以在理解抽象事物的时候,尽量将其和具象的事物建立联系。
2.1 dentry object
dentry代表一个路径中的一项,例如下面的路径就对应3个dentry
/tmp/mydata
3个dentry依次对应根目录/,根目录下的tmp文件夹,tmp文件夹下的文件mydata,每一个dentry都会记录着和他们相连的dentry。一个目录是需要对应文件(inode)的,否则他就是废路径,反之他就是积极的。其在内核在的定义如下
//include\linux\dcache.h
struct dentry {
unsigned int d_flags; /* protected by d_lock */
...
struct dentry *d_parent; /* parent directory */
struct qstr d_name;
struct inode *d_inode; /* Where the name belongs to - NULL is
...
};
2.2 inode object
inode就是具体的文件了,用来记录一个文件的信息。常见的文件、文件夹、FIFO在硬盘中都是由它代表的。如果文件系统时基于内存的那么它就存在于内存如(procfs、sysfs),位置则跟随文件系统的适用对象,这里指代的是它的主体。还有一种情况,则是内存和硬盘中都会存在的,例如使用vim打开基于磁盘的文件系统的一个文件,那么它会被读入内存,如果这个文件被改变了,相应的kernel也需要将内存中的数据刷入硬盘中去,所以这个过程是设计内存和硬盘的。一个inode是可以对于多个文件路径(dentry)的。其在内核在的定义如下
//include\linux\fs.h
struct inode {
umode_t i_mode;
struct super_block *i_sb;
...
};
2.3 superblock(SB)
代表已被挂载的文件系统,在没有挂载该文件系统前是不会实例化的。这个数据结构一般存储在硬盘中,用来记录被挂载文件系统的信息,可以理解成一个放置文件的容器。其在内核在的定义如下
//include\linux\path.h
struct path {
struct vfsmount *mnt;
struct dentry *dentry;
} __randomize_layout;
//include\linux\fs.h
struct super_block {
struct list_head s_list; /* Keep this first */
...
struct file_system_type *s_type;
struct dentry *s_root;
...
};
2.4 file
file用于描述被进程打开的inode的信息,只有进程打开一个inode的时候才会生成。并且所有被该进程打开的文件都会生成对应的file存在任务数据结构的数组中。在应用编程的过程中,open返回的fd实际上就是这个数组的下标。注意数组的0/1/2对应的file是固定的,其分别对应标准输出、标准输入、标准错误。该数据也是存在于内存的。其在内核在的定义如下
//include\linux\fs.h
struct file {
...
struct path f_path;
struct inode *f_inode; /* cached value */
const struct file_operations *f_op;
...
};
2.5 他们之间的关系图
下面是来自于ULK3中的关系图,画的很好供享用

3. 构建自定义的文件系统
下面是基于VFS实现的自定义类型的文件系统,暂且取名为flagstaff吧,下面是挂载好flagstaff文件系统的目录结构
board:/ # ls -lh /dev/flagstafffs/
-rw-rw-rw- 1 root root 0 2022-04-08 16:22 binder
-rw-rw-rw- 1 root root 0 2022-04-08 16:22 flagstaff-control
-rw-rw-rw- 1 root root 0 2022-04-08 16:22 hwbinder
-rw-rw-rw- 1 root root 0 2022-04-08 16:22 vndbinder
上面的示意图中,flagstaff文件系统的挂载点为目录/dev/flagstaffs。
3.1 注册 flagstaff 文件系统
注意了,对于使用了GKI的kernel,注册文件系统类型是不允许编译成模块的,必须加入到内核中去
+obj-y +=

本文详细介绍了VFS(虚拟文件系统)的概念、关键组件如dentry、inode和superblock的作用,以及如何基于VFS实现自定义文件系统flagstaff。通过实例展示了文件系统注册、挂载和内部结构的构建过程,包括创建文件、目录和定制文件操作。
最低0.47元/天 解锁文章
3970

被折叠的 条评论
为什么被折叠?



