超级块的结构为:
/* The Super Block comes first in the block group */
typedef struct tagEXT2_SUPER_BLOCK
{
uint32_t s_inodes_count; /* total no of inodes */
uint32_t s_blocks_count; /* total no of blocks */
uint32_t s_r_blocks_count; /* total no of blocks reserved for exclusive use of superuser */
uint32_t s_free_blocks_count; /* total no of free blocks */
uint32_t s_free_inodes_count; /* total no of free inodes */
uint32_t s_first_data_block; /* position of the first data block */
uint32_t s_log_block_size; /* used to compute logical block size in bytes */
uint32_t s_log_frag_size; /* used to compute logical fragment size */
uint32_t s_blocks_per_group; /* total number of blocks contained in the group */
uint32_t s_frags_per_group; /* total number of fragments in a group */
uint32_t s_inodes_per_group; /* number of inodes in a group */
uint32_t s_mtime; /* time at which the last mount was performed */
uint32_t s_wtime; /* time at which the last write was performed */
uint16_t s_mnt_count; /* number of time the fs system has been mounted in r/w mode without having checked */
uint16_t s_max_mnt_count; /* the max no of times the fs can be mounted in r/w mode before a check must be done */
uint16_t s_magic; /* a number that identifies the fs (eg. 0xef53 for ext2) */
uint16_t s_state; /* gives the state of fs (eg. 0x001 is Unmounted cleanly) */
uint16_t s_pad; /* unused */
uint16_t s_minor_rev_level; /* */
uint32_t s_lastcheck; /* the time of last check performed */
uint32_t s_checkinterval; /* the max possible time between checks on the fs */
uint32_t s_creator_os; /* os */
uint32_t s_rev_level; /* Revision level */
uint16_t s_def_resuid; /* default uid for reserved blocks */
uint16_t s_def_regid; /* default gid for reserved blocks */
/* for EXT2_DYNAMIC_REV superblocks only */
uint32_t s_first_ino; /* First non-reserved inode */
uint16_t s_inode_size; /* size of inode structure */
uint16_t s_block_group_nr; /* block group # of this superblock */
uint32_t s_feature_compat; /* compatible feature set */
uint32_t s_feature_incompat; /* incompatible feature set */
uint32_t s_feature_ro_compat; /* readonly-compatible feature set */
uint8_t s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
uint32_t s_algorithm_usage_bitmap; /* For compression */
uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
uint16_t s_padding1;
uint32_t s_reserved[204]; /* unused */
} EXT2_SUPER_BLOCK;
而ext2read中进行超级块的读取函数为mount,此函数:
int Ext2Partition::mount()
{
EXT2_SUPER_BLOCK sblock;
int gSizes, gSizeb; /* Size of total group desc in sectors */
char *tmpbuf;
//读取超级块数据,读取位置为分区的1024字节后的1024字节
read_disk(handle, &sblock, relative_sect + 2, 2, sect_size); /* read superBlock of root */
if(sblock.s_magic != EXT2_SUPER_MAGIC)
{
printf("Bad Super Block. The drive %s is not ext2 formatted.\n", linux_name.c_str());
return -1;
}
//判断此分区是否支持ext2的特性
if(sblock.s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
{
printf("File system compression is used which is not supported.\n");
}
//得到块的大小
blocksize = EXT2_BLOCK_SIZE(&sblock);
//得到每个group中有多少个inode
inodes_per_group = EXT2_INODES_PER_GROUP(&sblock);
//得到每个inode结构体的长度
inode_size = EXT2_INODE_SIZE(&sblock);
printf("Block size %d, inp %d, inodesize %d\n", blocksize, inodes_per_group, inode_size);
//得到总的group的个数,用整个分区的块数/每个group的块的个数
totalGroups = (sblock.s_blocks_count)/EXT2_BLOCKS_PER_GROUP(&sblock);
//得到分区所有的group描述信息的大小
gSizeb = (sizeof(EXT2_GROUP_DESC) * totalGroups);
//得到所有group描述信息所占的扇区数
gSizes = (gSizeb / sect_size)+1;
//为所有group分配描述信息的空间
desc = (EXT2_GROUP_DESC *) calloc(totalGroups, sizeof(EXT2_GROUP_DESC));
if(desc == NULL)
{
printf("Not enough Memory: mount: desc: Exiting\n");
exit(1);
}
//分配所有group描述信息所占的字节长度的存储空间
if((tmpbuf = (char *) malloc(gSizes * sect_size)) == NULL)
{
printf("Not enough Memory: mount: tmpbuf: Exiting\n");
exit(1);
}
/* Read all Group descriptors and store in buffer */
/* I really dont know the official start location of Group Descriptor array */
if((blocksize/sect_size) <= 2)
{
//relative_sect是本分区相对于整个硬盘的开始扇区号
read_disk(handle, tmpbuf, relative_sect + ((blocksize/sect_size) + 2), gSizes, sect_size);
}
else
{
//relative_sect是本分区相对于整个硬盘的开始扇区号,偏移一个块的大小是为什么?偏移一个块是因为第一个块存储的是Boot Block等相关的信息
read_disk(handle, tmpbuf, relative_sect + (blocksize/sect_size), gSizes, sect_size);
}
//得到所有的group信息存储到缓存desc中
memcpy(desc, tmpbuf, gSizeb);
free(tmpbuf);
return 0;
}