当前位置: 首页 > 工具软件 > Ext2Read > 使用案例 >

开源ext2read代码走读之-ext2文件系统中的超级块及对应代码

汤承允
2023-12-01
在进行分区时,每个分区就是一个文件系统,而每个文件系统开始位置的那个块就称为超级块。超级块的作用是存储文件系统的大小、空的和填满的块,以及它们各自的总数和其他诸如此类的信息。这也就是说,要使用这一个分区来进行数据访问时,第一个要经过的就是超级块,所以超级块坏了,这个磁盘也就回天乏术了。

super block的中文名称是超级块,它是硬盘分区开头——开头的第一个byte是byte 0,从 byte 1024开始往后的1024 bytes。 超级块中的数据其实就是文件卷的控制信息部分,也可以说它是卷资源表,有关文件卷的大部分信息都保存在这里。例如:硬盘分区中每个block的大小、硬盘分区上一共有多少个block group、以及每个block group中有多少个inode。

超级块的结构为:

/* 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;
}

 类似资料: