翻译自Linux文档中的vfs.txt
介绍VFS(Virtual File System)是内核提供的文件系统抽象层,其提供了文件系统的操作接口,可以隐藏底层不同文件系统的实现。
Directiry Entry Cache(dcache)VFS通过open()、stat()这些接口传入的文件名搜索dcache,快速找到文件名对应的dentry。dentry的结构是struct dentry,这只是一个内存结构,不会持久化到磁盘中,仅仅是为了提升性能而已。
dentry cache是整个文件空间的视图,但是大部分情况下并不能同时将所有dentry都加载到内存。VFS会在执行lookup()时,创建还不在内存中的dentry。
The Inode Objectinode代表真实存储在文件系统中的对象,比如文件、目录、FIFO等等。inode的结构是struct inode。一个dentry只能指向一个inode,但一个inode可以被多个dentry指向。
对于块设备的文件系统,inode存储在磁盘上,并在需要的时候拷贝到内存中,修改inode后又会写回磁盘进行持久化。对于伪文件系统,inode保存在内存中。
VFS调用lookup()从指定路径的第一级目录的dentry开始查找对应的inode。lookup()的真实实现是由inode所在的底层文件系统提供的。
The File Object打开一个文件实际就是创建一个file对象。file的结构是struct file,其有指向一个dentry的指针,和一组操作file的函数指针。这些信息是从inode中获取的。在打开文件的最后,file会被加入当前进程的文件描述符表中。
用户的读、写、关闭文件都通过fd进行,内核会可以根据fd获取到对应的file对象,这些操作最终都会调用到底层文件系统提供的函数。
注册和挂载文件系统注册和注销文件系统的函数如下
#include <linux/fs.h> extern int register_filesystem(struct file_system_type *); extern int unregister_filesystem(struct file_system_type *);当挂载文件系统时,VFS会调用底层文件系统指定的mount()函数,mount()会返回一个dentry作为文件系统的根目录。所有已挂载的文件系统,可以在/proc/filesystems中看到。
struct file_system_type该结构用于描述文件系统,自内核2.6.30,有如下定义
struct file_system_type { const char *name; int fs_flags; struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct list_head fs_supers; struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; };name:文件系统的名字,比如"ext2"等。
fs_flags:比如FS_REQUIRES_DEV、FS_NO_DCACHE等一些标志。
mount:挂载文件系统时调用。
kill_sb:卸载文件系统时调用。
owner:在大部分情况下,应当初始化为THIS_MODULE。
next:应当初始化为NULL。
s_lock_key,s_umount_key:用于检查死锁。
mount()的参数如下
struct file_system_type* fs_type:描述文件系统,其中部分底层文件系统初始化。
int flags:挂载的标志,如FS_REQUIRES_DEV,FS_NO_DCACHE等。
const char *dev_name:挂载的设备名。
void *data:任意的选项,通常是ASCII字符串。
mount()成功时,要求加锁并获得superblock的活动引用,返回dentry(可以是子目录的dentry),失败时返回ERR_PTR(error)。
grab_super()是获取活动引用的函数,即让spuer_block::a_active加1
mount()会创建一个superblock,其结构是struct superblock。struct superblock中有一个指向struct super_operations的指针s_op,其由一系列操作文件系统的函数指针组成。
VFS提供了如下方法挂载不同类型的文件系统
mount_bdev():挂载基于块设备的文件系统。
mount_nodev():挂载不基于设备的文件系统。
mount_single():挂载共享实例的文件系统。
这些函数都有一个入参int (*fill_super)(struct super_block *, void *, int),其用于初始化struct superblock的部分字段。
fill_super的参数如下
struct super_block *sb:指向superblock。
void *data:mount的参数,通常是一个ASCII字符串,需要自行解析。
int silent:确定是否输出错误信息。
The Superblock Object一个superblock代表了一个已挂载的文件系统。
struct super_operationsVFS通过struct super_operations操作superblock
struct super_operations { struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); void (*dirty_inode) (struct inode *, int flags); int (*write_inode) (struct inode *, int); void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *); int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); int (*show_options)(struct seq_file *, struct dentry *); ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); int (*nr_cached_objects)(struct super_block *); void (*free_cached_objects)(struct super_block *, int); };