linux文件系统2-linux虚拟文件系统

来源:互联网 发布:怎么查看服务器的域名 编辑:程序博客网 时间:2024/06/05 12:47

曾经在网上搜索过一个问题,为什么叫VFS--虚拟文件系统。网上有个帖子,给出了个这样的答案。虚拟文件系统,关键在于“虚拟”,也就是说VFS不是一个真正的文件系统,它仅仅提供真实文件系统的管理。另外有个帖子问一句话说什么是VFS,我觉得不错的回答是,VFS是文件系统与用户空间程序的一个接口。

1.与VFS相关的数据结构

     超级块结构:存放已安装的系统文件的相关信息。

     索引节点结构:存放有关文件的信息。

     文件结构:存放被进程打开的文件的相关信息。

     目录项:存放有关路径及路径名所指向的文件的信息。

1.1超级块结构

1.1.1

struct super_block{ /************描述具体文件系统的整体信息的域*****************          kdev_t s_dev;                /* 包含该具体文件系统的块设备标识符。例如,对于 /dev/hda1,其设备标识符为 0x301*/   unsigned long        s_blocksize;        /*该具体文件系统中数据块的大小,以字节为位 */                                                        unsigned char        s_blocksize_bits;   /*块大小的值占用的位数,例如,如果块大小为1024字节,则该值为10*/     unsigned long long   s_maxbytes;     /* 文件的最大长度 */   unsigned long        s_flags;                   /* 安装标志*/   unsigned long        s_magic;                        /*魔数,即该具体文件系统区别于其它文系统的一个标志*/ /**************用于管理超级块的域******************/   struct list_head     s_list;                /*指向超级块链表的指针*/     struct semaphore     s_lock                      /*锁标志位,若置该位,则其它进程不能对该超级块操作*/   struct rw_semaphore  s_umount                   /*对超级块读写时进行同步*/                                                                           unsigned   char s_dirt;          /*脏位,若置该位,表明该超级块已被修改*/                                                             struct dentry     *s_root; /*指向该具体文件系统安装目录的目录项。*/   int                  s_count;/*对超级块的使用计数*/   atomic_t             s_active;                               struct list_head     s_dirty;        /*已修改的索引节点形成的链表 */   struct list_head     s_locked_inodes;/* 要进行同步的索引节点形成的链表*/   struct list_head     s_files;
/***********和具体文件系统相联系的域*************************/   struct file_system_type *s_type;                     /*指向文件系统的file_system_type 数据结构的指针 */                                                   struct super_operations *s_op;         /*指向某个特定的具体文件系统的用于超级块操作的函数集合 */                                            struct dquot_operations *dq_op;            /* 指向某个特定的具体文件系统用于限额操作的函数集合 */                                               struct quotact_ops      *sqcop                       /*一个共用体,其成员是各种文件系统 的 fsname_sb_info数据结构 */                                    };
超级块的重要信息:

(1)s_list域

s_list域是list_head类型的,它指向双向循环链表中的前一个元素和下一个元素的指针,这个超级块被嵌入双向循环链表中。

(2)s_maxbytes

文件系统所允许的文件的最大长度。

(3)file_sysytm_type* s_type

超级块结构中包含通用文件系统的具体信息。

struct file_system_type {     const char *name; //文件系统的名称     int fs_flags;     int (*get_sb) (struct file_system_type *, int,const char *, void *, struct vfsmount *);
//这个函数用于取得本文件系统的super_block,并将之填充到相应的struct vfsmount的mnt_sb成员中。     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;};

下图展示了文件系统和超级块之间的联系。


(4)super_operations *s_op 

这个数据类型保存超级块的操作。

(5)s_dirty域

它指向属于这个文件系统的脏索引节点链表的第一个和最后一个元素。

(6)dentry  *s_root

dentry结构体用于保存文件的路径名。这个特殊的dentry对象是与安装目录对应的目录项对象。这就是属于它的super_block。

(7)s_files

它指向文件结构体链表的第一个元素,这个文件结构体链表不但正在使用,而且已被分配给超级块。

(8)s_instances

它指向超级块链表中相邻的超级块元素,链表中的超级块是同一种文件系统。


1.1.2超级块的操作

它的定义在 include/linux/fs.h头文件中可以看到

1560struct super_operations {1561        struct inode *(*alloc_inode)(struct super_block *sb); 1562        void (*destroy_inode)(struct inode *); 15631564        void (*dirty_inode) (struct inode *); 1565        int (*write_inode) (struct inode *, struct writeback_control *wbc); 1566        int (*drop_inode) (struct inode *); 1567        void (*evict_inode) (struct inode *);1568        void (*put_super) (struct super_block *); 1569        void (*write_super) (struct super_block *); 1570        int (*sync_fs)(struct super_block *sb, int wait); 1571        int (*freeze_fs) (struct super_block *);1572        int (*unfreeze_fs) (struct super_block *);1573        int (*statfs) (struct dentry *, struct kstatfs *); 1574        int (*remount_fs) (struct super_block *, int *, char *);1575        void (*umount_begin) (struct super_block *);15761577        int (*show_options)(struct seq_file *, struct vfsmount *);1578        int (*show_stats)(struct seq_file *, struct vfsmount *);1579#ifdef CONFIG_QUOTA1580        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);1581        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);1582#endif1583        int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);1584}; a.struct inode * alloc_inode(struct super_block * sb) :创建和初始化一个新的索引结点。b.void destroy_inode(struct super_block *sb) :释放指定的索引结点 。c.void dirty_inode(struct inode *inode) :VFS在索引节点被修改时会调用此函数。d.void  write_inode(struct inode *inode, struct writeback_control *wbc) 将指定的inode写回磁盘。e.void  drop_inode( struct inode * inode):删除索引节点。f.void   put_super(struct super_block *sb) :用来释放超级块。g.void  write_super(struct super_block *sb):更新磁盘上的超级块。h.void   sync_fs(struct super_block *sb,in wait):使文件系统的数据元素与磁盘上的文件系统同步,wait参数指定操作是否同步。i.int statfs(struct super_block *sb,struct statfs *statfs):获取文件系统状态。把文件系统相关的统计信息放在statfs中。


1.2索引节点的结构

文件系统处理文件或目录时的所有信息都存放在称为索引节点的数据结构中。具体文件系统的索引节点是存放在磁盘上的,是一种静态结构,要使用它,必须将其调入内存,填写VFS的索引节点。VFS索引节点也称为动态节点。(即索引节点仅当文件被访问的时候才在内存中创建)。

725struct inode { 726        struct hlist_node       i_hash;                      //散列表 727        struct list_head        i_list;                      //索引节点链表 728        struct list_head        i_sb_list;                   //链接一个文件系统中所有inode的链表  729        struct list_head        i_dentry;                    //目录项链表  730        unsigned long           i_ino;                       //索引节点号 731        atomic_t                i_count;                     //引用计数 732        unsigned int            i_nlink;                     //硬连接数 733        uid_t                   i_uid;                       //使用者的id 734        gid_t                   i_gid;                       //使用组id  735        dev_t                   i_rdev;                      //实际设备标识符号 736        unsigned int            i_blkbits;                    737        u64                     i_version;                   //版本号 738        loff_t                  i_size;                      //以字节为单位 739#ifdef __NEED_I_SIZE_ORDERED 740        seqcount_t                  i_size_seqcount;      741#endif 742        struct timespec         i_atime;                     //最后访问时间 743        struct timespec         i_mtime;                     //最后修改时间 744        struct timespec         i_ctime;                     //最后改变时间  745        blkcnt_t                i_blocks;                //文件的块数 746        unsigned short          i_bytes;                     //使用的字节数 747        umode_t                 i_mode;                    //访问权限控制  748        spinlock_t              i_lock;                      //自旋锁 749        struct mutex            i_mutex;                 750        struct rw_semaphore     i_alloc_sem;                 751        const struct inode_operations   *i_op;               //索引节点操作表 752        const struct file_operations    *i_fop;              //文件操作表 753        struct super_block      *i_sb;                       //相关的超级块  754        struct file_lock        *i_flock;                    //文件锁链表 755        struct address_space    *i_mapping;                  //相关的地址映射 756        struct address_space    i_data;                      //设备地址映射 757#ifdef CONFIG_QUOTA 758        struct dquot            *i_dquot[MAXQUOTAS];  //节点的磁盘限额 759#endif 760        struct list_head        i_devices;                  //块设备链表 761        union { 762                struct pipe_inode_info  *i_pipe;            //管道信息 763                struct block_device     *i_bdev;           //块设备驱动 764                struct cdev             *i_cdev;                765        }; 766 767        __u32                   i_generation;               //索引节点版本号 768 769#ifdef CONFIG_FSNOTIFY 770        __u32                   i_fsnotify_mask; /* all events this inode cares about */ 771        struct hlist_head       i_fsnotify_marks;    772#endif 773 774        unsigned long           i_state;                  //状态标志 775        unsigned long           dirtied_when;            //首次修改时间 776 777        unsigned int            i_flags;                 //文件系统标志 778 779        atomic_t                i_writecount;            //写者计数 780#ifdef CONFIG_SECURITY 781        void                    *i_security;            //安全模块 782#endif 783#ifdef CONFIG_FS_POSIX_ACL 784        struct posix_acl        *i_acl; 785        struct posix_acl        *i_default_acl; 786#endif 787        void                    *i_private; /* fs or device private pointer */ 788};

索引节点链表分成三类:

链表i_count是否脏  引用指针未使用i_count=0不脏inode_unused使用i_coun>0不脏inode_in_use脏索引节点i_count>0脏超级块的s_dirty域索引节点和超级块的关系如下图所示:

(1)i_hash域

它包含一个指向哈希表的指针,哈希表用来加速索引节点的查找。

(2)i_list域

这个域连接索引节点链表中相邻的结构。

(3)i_dentry

这个域指向与文件对应的dentry结构体的链表。

(4)i_ino域

这个域保存独一无二的索引节点号。 

(5)i_sb域

这个域保存有一个指针指向文件所驻留的文件系统的超级块。

(6)i_state

带有I_LOCK 和I_DIRTY标志集的索引节点在inode_in_use链表。如果没有这两个标志,就把索引节点添加到inode_unuse链表。

1.3目录项结构

dentry结构表示目录中的一项。VFS用它了解基于系统目录命名、目录组织和文件逻辑布局之间的关系。


 

(1)d_inode域

d_inode指向与目录项相关的文件对应的索引节点。

(2)指向目录项链表中相邻元素的指针。

d_alias 指针指向已使用的目录项链表,d_lru指向未使用的目录项指针。

(3)dop域

d_op指向目录项的操作表

(4)d_sb域

指向与目录项表示的分量相关的超级块。

(5)d_parent

保存指向父目录项或路径名中父分量对应的目录项的指针。

1.4文件结构

 89struct dentry {  90        atomic_t d_count;                //使用计数  91        unsigned int d_flags;           //目录项标时  92        spinlock_t d_lock;                  //单目录锁  93        int d_mounted;                      //目录项的安装点  94        struct inode *d_inode;              //与该目录项相关联的索引节点   95                                          96        /*  97         * The next three fields are touched by __d_lookup.  Place them here  98         * so they all fit in a cache line.  99         */ 100        struct hlist_node d_hash;        //散列表 101        struct dentry *d_parent;            //父目录项 102        struct qstr d_name;                 //目录项名可快速查找 103 104        struct list_head d_lru;             // 未使用目录以LRU 算法链接的链表 105        /* 106         * d_child and d_rcu can share memory 107         */ 108        union { 109                struct list_head d_child;       /* child of parent list */ 110                struct rcu_head d_rcu; 111        } d_u; 112        struct list_head d_subdirs;        //该目录项子目录项所形成的链表 113        struct list_head d_alias;          //索引节点别名链表 114        unsigned long d_time;             //重新生效时间 115        const struct dentry_operations *d_op;        // 操作目录项的函数 116        struct super_block *d_sb;         //目录项树的根 117        void *d_fsdata;                   //具体文件系统的数据 118 119        unsigned char d_iname[DNAME_INLINE_LEN_MIN];    //短文件名 120};

内核使用双向循环链表来保存文件结构。共有三个链表:

free_list全局变量,空闲文件对象链表,由所有可用的文件对象组成的双向链表。

anon_list全局变量,正在使用,但是没有分配的文件对象链表。

级块的s_files,超级块的文件对象链表。

  

struct vfsmount { struct list_head mnt_hash; struct vfsmount *mnt_parent; /* fs we are mounted on */      struct dentry *mnt_mountpoint; /* dentry of mountpoint */ struct dentry *mnt_root; /* root of the mounted tree */ struct super_block *mnt_sb; /* pointer to superblock */ struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ int mnt_flags; /* 4 bytes hole on 64bits arches */ const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct list_head mnt_share; /* circular list of shared mounts */ struct list_head mnt_slave_list;/* list of slave mounts */ struct list_head mnt_slave; /* slave list entry */ struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ struct mnt_namespace *mnt_ns; /* containing namespace */ atomic_t __mnt_writers;...};



(1)f_list
    指向链表中相邻文件结构的指针。
(2)f_dentry域
   指向与文件相关的目录项结构的指针。
(3)f_vfsmnt域
   指向vfsmount结构的指针。
(4)f_op域
   指向file_operations结构的指针,它被保存可被用应用于文件的操作表。
   全局链表和局部链表的应用。
内核保存的全局变量以及这些变量指向的链表类型如下:
全局变量                    结构类型
super_blocks super_block
file_systems   file_sysytem_type
dentry_unused    dentry
vfsmountlist   vfsmount
inode_in_use   inode
inode_unuse   inode

原创粉丝点击