8.2.1  超级块

很多具体文件系统中都有超级块结构,超级块是这些文件系统中最重要的数据结构,它是来描述整个文件系统信息的,可以说是一个全局的数据结构。MinixExt2等有超级块,VFS也有超级块,为了避免与后面介绍的Ext2超级块发生混淆,这里用VFS超级块来表示。VFS超级块是各种具体文件系统在安装时建立的,并在这些文件系统卸载时自动删除,可见,VFS超级块确实只存在于内存中,同时提到VFS超级块也应该说成是哪个具体文件系统的VFS超级块。VFS超级块在inculde/fs/fs.h中定义,即数据结构super_block,该结构及其主要域的含义如下:

 

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;            /* 指向某个特定的具体文件系统

                                        用于限额操作的函数集合 */                                                                               

u;                                /*一个共用体,其成员是各种文件系统

                                       fsname_sb_info数据结构 */                                                                                      

};

所有超级块对象(每个已安装的文件系统都有一个超级块)以双向环形链表的形式链接在一起。链表中第一个元素和最后一个元素的地址分别存放在super_blocks变量的s_list域的 next prev域中。s_list域的数据类型为struct list_head,在超级块的s_dirty域以及内核的其他很多地方都可以找到这样的数据类型;这种数据类型仅仅包括指向链表中的前一个元素和后一个元素的指针。因此,超级块对象s_list域包含指向链表中两个相邻超级块对象的指针。图8.2说明了list_head 元素、next prev是如何嵌入到超级块对象中的。

super_blocks

 

next

prev

 

 

 

                        超级块                超级块                 超级块     


                                                                             

 

 

8.2 超级块链表

超级块最后一个u 联合体域包括属于具体文件系统的超级块信息:

         union {

                struct Minix_sb_info    Minix_sb;

                struct Ext2_sb_info     Ext2_sb;

                struct ext3_sb_info     ext3_sb;

                struct hpfs_sb_info     hpfs_sb;

                struct ntfs_sb_info     ntfs_sb;

                struct msdos_sb_info    msdos_sb;

                struct isofs_sb_info    isofs_sb;

                struct nfs_sb_info      nfs_sb;

                struct sysv_sb_info     sysv_sb;

                struct affs_sb_info     affs_sb;

                struct ufs_sb_info      ufs_sb;

                struct efs_sb_info      efs_sb;

                struct shmem_sb_info    shmem_sb;

                struct romfs_sb_info    romfs_sb;

                struct smb_sb_info      smbfs_sb;

                struct hfs_sb_info      hfs_sb;

                struct adfs_sb_info     adfs_sb;

                struct qnx4_sb_info     qnx4_sb;

                struct reiserfs_sb_info reiserfs_sb;

                struct bfs_sb_info      bfs_sb;

                struct udf_sb_info      udf_sb;

               struct ncp_sb_info      ncpfs_sb;

                struct usbdev_sb_info   usbdevfs_sb;

               struct jffs2_sb_info    jffs2_sb;

               struct cramfs_sb_info   cramfs_sb;

                void                    *generic_sbp;

       } u;

通常,为了效率起见u域的数据被复制到内存。任何基于磁盘的文件系统都需要访问和更改自己的磁盘分配位示图,以便分配和释放磁盘块。VFS允许这些文件系统直接对内存超级块的u联合体域进行操作,无需访问磁盘。

但是,这种方法带来一个新问题:有可能VFS超级块最终不再与磁盘上相应的超级块同步。因此,有必要引入一个s_dirt标志,来表示该超级块是否是脏的,也就是说,磁盘上的数据是否必须要更新。缺乏同步还导致我们熟悉的一个问题:当一台机器的电源突然断开而用户来不及正常关闭系统时,就会出现文件系统崩溃。Linux是通过周期性地将所有“脏”的超级块写回磁盘来减少该问题带来的危害。

与超级块关联的方法就是所谓的超级块操作。这些操作是由数据结构super_operations来描述的,该结构的起始地址存放在超级块的s_op域中,稍后将与其他对象的操作一块介绍。