linux的虚拟文件系统VFS

    虚拟文件系统(virtual file system),别名虚拟文件系统开关,是linux中的一个软件层,向用户空间提供文件系统操做接口。html

    VFS包含的系统调用包括open(2)、stat(2)、read(2)、write(2)、chmod(2)等等,这些系统调用在进程环境中执行。下面几个重要的数据结构是VFS(虚拟文件系统中涉及到的数据结构):node

    一、Directory Entry Cache(dcache)linux

    VFS实现了系统调用open(2)、stat(2)、chmod(2),和其余相似的文件系统调用。用于这些系统调用中的参数被VFS用来进行directory entry cache的对象搜索,其中directory entry cache有多个名字,好比dentry cache或者dcache。 经过dentry cache提供了一种快速查找机制,能够快速的根据路径名字找到具体的dentry。须要特别说明的是:dentry是存在于内存中的,不会保存到磁盘上进行永久性存储的。数据结构

    二、inode 对象函数

    每个dentry对象都有一个指针指向具体的inode对象。inode是文件系统的对象,好比正规文件(regular file)、目录(directory)、FIFO(管道)。这些inode对象存在于磁盘(块设备文件文件系统)或者内存(linux下的伪文件系统procfs)。若是是存在于磁盘上的inode对象则须要加载到内存中去,当发生的改变须要保存到磁盘上去。一个inode对象可能有多个dentry对象指向它(由于linux下实现了硬链接特性)。spa

    为了查找一个具体的inode对象须要在父目录的inode上执行lookup操做。而具体的lookup方法是由inode存放的文件系统具体的实现,这个操做是由具体的文件系统进行初始化。一旦VFS拥有具体的dentry对象的时候,不少系统调用就能够迅速完成,好比stat(2)系统调用,它就是获取inode上的数据,根据dentry上的指针能够迅速的找到inode对象。.net

    三、File对象指针

    打开一个文件还须要另一个操做:分配一个File结构的对象(这是linux内核端的文件描述符的实现)。新申请的File对象初始化了一个指针指向dentry对象和多个文件操做函数(好比read、write、mmap等操做)。File数据结构放在这个进程的文件描述表中(file descriptor table)。code

    用户空间的read、write等操做都是经过用户空间态(userspace file descriptor)的描述符得到正确的File结构,而后调用File结构中的具体的方法。只要文件处于打开状态,linux内核中就有对应的dentry对象,天然也有对象的inode对象。orm

    四、文件系统对象(filesystem)

    登记和卸载一个文件系统使用下面的函数调用。    

    #include <linux/fs.h>


     extern  int register_filesystem( struct file_system_type *);

     extern int unregister_filesystem(struct file_system_type *); 

    传入的参数struct file_system_type描述了具体的文件系统。当发出一个命令,须要在你的名字空间的一个目录上挂载一个文件系统的时候,VFS会调用具体文件中的mount方法。当mount操做完成以后,会返回一个struct dentry对象,这个时候会新建一个vfsmount对象,用于指向这个dentry对象,同时这个vfsmount对象会添加到这个挂载点上。因此当路径解析到达这个目录的时候,会跳转到这个vfsmount指向的文件系统中去。

    在/proc/filesystems下能够观察到全部挂载的文件系统。

    如下是file_system_type结构:

    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”,“ext3”,“ext4”,“msdos”等

    fs_flags:一些标志,好比:FS_REQUIRES_DEV, FS_NO_DCACHE

    mount:重要的field,当一个filesystem实例化的时候须要具体的filesystem的mount方法

    五、superblock对象 

    一个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 *,  intchar *, size_t, loff_t);
        ssize_t (*quota_write)( struct super_block *,  intconst  char *, size_t, loff_t);
int (*nr_cached_objects)( struct super_block *);
         void (*free_cached_objects)( struct super_block *,  int);

    };

   全部的方法都没有lock来维持,这说明了这些方法只能够在一个进程上下文中执行,不能在中断上下文中执行。

   六、address space对象 

   address_space对象用于对page cache中的page进行分组和管理。它能够用来跟踪一个文件中的page cache和一个文件中映射到进程地址空间中的文件区域。

   address space提供了大量有显著特征的服务,好比根据经过地址查找page,追踪标志为Dirty或者WriteBack的page。

 

   Further Reading:

   1.Creating Linux virtual filesystems. 2002. http://lwn.net/Articles/13325/

   2.A tour of the Linux VFS by Michael K. Johnson. 1996. http://www.tldp.org/LDP/khg/HyperNews/get/fs/vfstour.html