1、首先了解下block,对于ext2(ext3)文件系统而言,硬盘分区首先被划分为一个个的block,同一个ext2文件系统上的每个block大小都是一样的。但是对于不同的ext2文件系统,block的大小可以有区别。典型的block大小是1024 bytes或者4096 bytes。这个大小在创建ext2、ext3文件系统的时候被决定,mkfs –t ext2/3 –b xx就可以设定块大小了!一个硬盘分区上的block计数是从0开始的,总的来说,block这个概念好理解。
2、理解了block的概念后,接着就是对block group的理解,硬盘分区上所有的block被聚在一起分成几个大的block group。其中每个block group中有多少个block是固定的。从上面的图可以看出来!每个block group都相对应一个group descriptor,每个group descriptor当中有几个重要的block指针,指向block group中的inode table、block bitmap和inode bitmap。
以上三个结构记载了其所属block group的许多信息。
3、下面就是对super block的理解了
Super block即为超级块,它是硬盘分区开头——开头的第一个byte是byte 0,从 byte 1024开始往后的一部分数据。由于block size最小是 1024 bytes,所以super block可能是在block 1中(此时block 的大小正好是 1024 bytes)
超级块中的数据其实就是文件卷的控制信息部分,也可以说它是卷资源表,有关文件卷的大部分信息都保存在这里。例如:硬盘分区中每个block的大小、硬盘分区上一共有多少个block group、以及每个block group中有多少个inode。
对于super block的结构和涵义可以通过查看/usr/include/linux/ext3_fs.h文件:
通过set number:
386 struct ext3_super_block {
386 struct ext3_super_block {
387 /*00*/ __le32 s_inodes_count; /* Inodes count */
388 __le32 s_blocks_count; /* Blocks count */
389 __le32 s_r_blocks_count; /* Reserved blocks count */
390 __le32 s_free_blocks_count; /* Free blocks count */
391 /*10*/ __le32 s_free_inodes_count; /* Free inodes count */
392 __le32 s_first_data_block; /* First Data Block */
393 __le32 s_log_block_size; /* Block size */
394 __le32 s_log_frag_size; /* Fragment size */
395 /*20*/ __le32 s_blocks_per_group; /* # Blocks per group */
396 __le32 s_frags_per_group; /* # Fragments per group */
397 __le32 s_inodes_per_group; /* # Inodes per group */
398 __le32 s_mtime; /* Mount time */
399 /*30*/ __le32 s_wtime; /* Write time */
400 __le16 s_mnt_count; /* Mount count */
401 __le16 s_max_mnt_count; /* Maximal mount count */
402 __le16 s_magic; /* Magic signature */
403 __le16 s_state; /* File system state */
404 __le16 s_errors; /* Behaviour when detecting errors */
405 __le16 s_minor_rev_level; /* minor revision level */
406 /*40*/ __le32 s_lastcheck; /* time of last check */
407 __le32 s_checkinterval; /* max. time between checks */
408 __le32 s_creator_os; /* OS */
409 __le32 s_rev_level; /* Revision level */
410 /*50*/ __le16 s_def_resuid; /* Default uid for reserved blocks */
411 __le16 s_def_resgid; /* Default gid for reserved blocks */
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 vfsmount结构描述的是一个独立文件系统的挂载信息,每个不同挂载点对应一个独立的vfsmount结构,属于同一文件系统的所有目录和文件隶属于同一个vfsmount,该vfsmount结构对应于该文件系统顶层目录,即挂载目录
2 比如对于mount /dev/sdb1 /media/Kingston,挂载点为/media/Kingston,对于Kingston这个目录,其产生新的vfsmount,独立于根文件系统挂载点/所在的vfsmount;
3 所有的vfsmount挂载点通过mnt_list双链表挂载于mnt_namespace->list链表中,该mnt命名空间可以通过任意进程获得
4 子vfsmount挂载点结构通过mnt_mounts挂载于父vfsmount的mnt_child链表中,并且mnt_parent直接指向父亲fs的vfsmount结构,从而形成层次结构
5 vfsmount的super_block结构->statfs函数可以获得该文件系统中空间的使用情况
6 对于挂载点/media/Kingston来讲,其vfsmount->mnt_root->f_dentry->d_name.name = '/';而vfsmount->mnt_mountpoint->f_dentry->d_name.name = 'Kingston'。对于/media/Kingston下的所有目录和文件而言,都是这样的。
进程每打开一个文件,就会有一个file结构与之对应。同一个进程可以多次打开同一个文件而得到多个不同的file结构,file结构描述了被打开文件的属性,读写的偏移指针等等当前信息。
两个不同的file结构可以对应同一个dentry结构。进程多次打开同一个文件时,对应的只有一个dentry结构。Dentry结构存储目录项和对应文件(inode)的信息。
在存储介质中,每个文件对应唯一的inode结点,但是,每个文件又可以有多个文件名。即可以通过不同的文件名访问同一个文件。这里多个文件名对应一个文件的关系在数据结构中表示就是dentry和inode的关系。
Inode中不存储文件的名字,它只存储节点号;而dentry则保存有名字和与其对应的节点号,所以就可以通过不同的dentry访问同一个inode。
不同的dentry则是同个文件链接(ln命令)来实现的。
目录项对象
每个文件除了有一个索引节点inode数据结构外,还有一个目录项dentry(directory enrty)数据结构。dentry 结构中有个d_inode指针指向相应的inode结构。读者也许会问,既然inode结构和dentry结构都是对文件各方面属性的描述,那为什么不把这两个结构“合而为一”呢?这是因为二者所描述的目标不同,dentry结构代表的是逻辑意义上的文件,所描述的是文件逻辑上的属性,因此,目录项对象在磁盘上并没有对应的映像;而inode结构代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统(如Ext2),Ext2_ inode结构在磁盘上就有对应的映像。所以说,一个索引节点对象可能对应多个目录项对象。
下面对dentry结构给出进一步的解释。
一个有效的dentry结构必定有一个inode结构,这是因为一个目录项要么代表着一个文件,要么代表着一个目录,而目录实际上也是文件。