ext2元数据结构

概述

本篇博客主要描述ext2文件系统中的各种典型元数据结构,其中包括文件系统级别的元数据,如超级块,块组描述符等,也包括文件级的元数据,如文件目录项,文件inode等。

ext2超级块

这里的超级块指的是ext2文件系统存储在磁盘上的超级块结构,之所以这么说是因为每个文件系统除了存储在磁盘上的超级块外,还在内存中也存储了一个超级块结构,基本上内存中的超级块是在磁盘超级块的基础上增加了一些额外的管理信息而成,因此,在这里我们主要关注的是ext2存储在磁盘上的超级块的数据结构。

ext2磁盘超级块的定义如下:

 1 /*
 2  * Structure of the super block
 3  */
 4 struct ext2_super_block {
 5     __le32    s_inodes_count;        /* Inodes count 索引节点总数*/
 6     __le32    s_blocks_count;        /* Blocks count 块大小,即文件系统以块为单位的大小*/
 7     __le32    s_r_blocks_count;    /* Reserved blocks count */
 8     __le32    s_free_blocks_count;    /* Free blocks count */
 9     __le32    s_free_inodes_count;    /* Free inodes count */
10     __le32    s_first_data_block;    /* First Data Block */
11     __le32    s_log_block_size;    /* Block size */
12     __le32    s_log_frag_size;    /* Fragment size */
13     __le32    s_blocks_per_group;    /* # Blocks per group 每个块组中的块数*/
14     __le32    s_frags_per_group;    /* # Fragments per group */
15     __le32    s_inodes_per_group;    /* # Inodes per group 每个块组中的索引节点个数*/
16     __le32    s_mtime;        /* Mount time */
17     __le32    s_wtime;        /* Write time */
18     __le16    s_mnt_count;        /* Mount count */
19     __le16    s_max_mnt_count;    /* Maximal mount count */
20     __le16    s_magic;        /* Magic signature */
21     __le16    s_state;        /* File system state */
22     __le16    s_errors;        /* Behaviour when detecting errors */
23     __le16    s_minor_rev_level;     /* minor revision level */
24     __le32    s_lastcheck;        /* time of last check */
25     __le32    s_checkinterval;    /* max. time between checks */
26     __le32    s_creator_os;        /* OS */
27     __le32    s_rev_level;        /* Revision level */
28     __le16    s_def_resuid;        /* Default uid for reserved blocks */
29     __le16    s_def_resgid;        /* Default gid for reserved blocks */
30     /*
31      * These fields are for EXT2_DYNAMIC_REV superblocks only.
32      *
33      * Note: the difference between the compatible feature set and
34      * the incompatible feature set is that if there is a bit set
35      * in the incompatible feature set that the kernel doesn‘t
36      * know about, it should refuse to mount the filesystem.
37      *
38      * e2fsck‘s requirements are more strict; if it doesn‘t know
39      * about a feature in either the compatible or incompatible
40      * feature set, it must abort and not try to meddle with
41      * things it doesn‘t understand...
42      */
43     __le32    s_first_ino;         /* First non-reserved inode */
44     __le16   s_inode_size;         /* size of inode structure */
45     __le16    s_block_group_nr;     /* block group # of this superblock */
46     __le32    s_feature_compat;     /* compatible feature set */
47     __le32    s_feature_incompat;     /* incompatible feature set */
48     __le32    s_feature_ro_compat;     /* readonly-compatible feature set */
49     __u8    s_uuid[16];        /* 128-bit uuid for volume */
50     char    s_volume_name[16];     /* volume name */
51     char    s_last_mounted[64];     /* directory where last mounted */
52     __le32    s_algorithm_usage_bitmap; /* For compression */
53     /*
54      * Performance hints.  Directory preallocation should only
55      * happen if the EXT2_COMPAT_PREALLOC flag is on.
56      */
57     __u8    s_prealloc_blocks;    /* Nr of blocks to try to preallocate*/
58     __u8    s_prealloc_dir_blocks;    /* Nr to preallocate for dirs */
59     __u16    s_padding1;
60     /*
61      * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
62      */
63     __u8    s_journal_uuid[16];    /* uuid of journal superblock */
64     __u32    s_journal_inum;        /* inode number of journal file */
65     __u32    s_journal_dev;        /* device number of journal file */
66     __u32    s_last_orphan;        /* start of list of inodes to delete */
67     __u32    s_hash_seed[4];        /* HTREE hash seed */
68     __u8    s_def_hash_version;    /* Default hash version to use */
69     __u8    s_reserved_char_pad;
70     __u16    s_reserved_word_pad;
71     __le32    s_default_mount_opts;
72      __le32    s_first_meta_bg;     /* First metablock block group */
73     __u32    s_reserved[190];    /* Padding to the end of the block */
74 };

可以看到,ext2磁盘超级块结构中大部分是描述整个文件系统的信息,如文件系统中块组的数量,inode数量,磁盘块的数量等等,不一而足,基本上从代码的注释我们就能比较清楚各个成员的含义,而且在后续的文章中我们或多或少地也会遇到这些成员,另外ext2超级块的最后一部分成员是为了兼容ext3而设计的,可能是为了更方便地从ext2升级至ext3吧,当然这只是我的猜测而已。

ext2块组描述符

前面的描述中我们知道,ext2文件系统将磁盘(分区)划分成大小相等的块组,以提高文件存取的连续性。而且块组中存在inode表,inode位图,数据块位图中众多信息,因此,有必要对每个块组生成一个描述符来管理块组,在ext2中,该数据结构如下定义:

/*
 * Structure of a blocks group descriptor
 */
struct ext2_group_desc
{
    __le32    bg_block_bitmap;        /* Blocks bitmap block */
    __le32    bg_inode_bitmap;        /* Inodes bitmap block */
    __le32    bg_inode_table;        /* Inodes table block */
    __le16    bg_free_blocks_count;    /* Free blocks count */
    __le16    bg_free_inodes_count;    /* Free inodes count */
    __le16    bg_used_dirs_count;    /* Directories count */
    __le16    bg_pad;
    __le32    bg_reserved[3];
};

相对来说,块组描述符简单得多了,记录了块组中数据块位图和inode位图的块号这些块号是相对于块组而言的,而非绝对块号,另外还记录了该块组中创建的目录数量,之所以记录这个是在后来创建目录时会将其作为考虑的参数,之所以这样做的目的是将目录分散在文件系统的所有块组中,避免某些块组过满而另外一些较为空闲的情况,当然这只是一种很简单的策略,效果也不见得多好。

ext2文件目录项

熟悉文件系统的朋友都知道,在linux文件系统中是通过目录一级一级索引直至找到最终的文件。文件是被组织在目录下的,要先找到文件我们必须先定位其所在目录,而且在linux中,一切皆文件,目录也是一个文件,也有数据块,其数据块中保存的是该目录下所有文件和子目录的文件目录项,因此,linux下文件查找的过程便是读出目录的数据块,在其中查找感兴趣的文件的文件目录项,进而访问文件更详细的信息

因此,对于ext2文件来说,每个文件的首先的元数据信息便是文件目录项,而且它是存储在磁盘上的,只不过它是存储在父目录的数据块中,但这并不影响其重要性,ext2文件系统的文件目录项结构如下:

struct ext2_dir_entry_2 {
    __le32    inode;            /* Inode number inode编号 */
    __le16    rec_len;        /* Directory entry length */
    __u8    name_len;        /* Name length */
    __u8    file_type;
    char    name[EXT2_NAME_LEN];    /* File name */
};

文件目录项主要是存储文件名至文件inode的映射关系,这样,根据文件名在父目录数据块中查找感兴趣文件就能获取该文件的inode号,进而可以得到该文件的所有信息

在该结构中,inode代表该文件inode编号,rec_len表示本文件目录项的大小,为什么需要这个rec_len呢,结构体定义好了整个长度不也就确认了嘛?非也,这是因为该结构体的最后一个成员name并不是固定长度的,其最大可以支持256字节,因此必须要有一个长度域来保存当前目录项长度,name_len指的是文件名长度,既然已经有了rec_len,为什么还需要文件名长呢,岂不多此一举?这是考虑到存在文件名填充的问题。从效率上来考虑,每个struct ext2_dir_entry_2最终都会被填充成4字节整数倍,对于目录项不是4字节整数倍的,需要在最后name文件名后面填充若干个0,因此name_len中记录的便是name[]域中有效文件名长度(即不包含0)。考虑下图所示事例:

1. “.”和“..”文件名后都填充了‘\0’以使文件目录项总长度为4的整数倍;

2. music和src文件/目录均也填充了‘\0’以使文件目录项总长度为4的整数倍;

3. test.txt因为其文件目录项已经是16个字节,无需填充。

ext2索引节点

该数据结构可能是一个文件最重要的元数据信息了,因为描述文件的一切属性都保存在这里了(除了文件名),重要性不言而喻,而且索引节点也是持久化存储在磁盘之上,每个块组都有专门的inode表来存储文件索引节点,ext2的索引节点结构如下所描述:

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
    __le16    i_mode;        /* File mode */
    __le16    i_uid;        /* Low 16 bits of Owner Uid */
    __le32    i_size;        /* Size in bytes */
    __le32    i_atime;    /* Access time */
    __le32    i_ctime;    /* Creation time */
    __le32    i_mtime;    /* Modification time */
    __le32    i_dtime;    /* Deletion Time */
    __le16    i_gid;        /* Low 16 bits of Group Id */
    __le16    i_links_count;    /* Links count */
    __le32    i_blocks;    /* Blocks count */
    __le32    i_flags;    /* File flags */
    union {
        struct {
            __le32  l_i_reserved1;
        } linux1;
        struct {
            __le32  h_i_translator;
        } hurd1;
        struct {
            __le32  m_i_reserved1;
        } masix1;
    } osd1;                /* OS dependent 1 */
    __le32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
    __le32    i_generation;    /* File version (for NFS) */
    __le32    i_file_acl;    /* File ACL */
    __le32    i_dir_acl;    /* Directory ACL */
    __le32    i_faddr;    /* Fragment address */
    union {
        struct {
            __u8    l_i_frag;    /* Fragment number */
            __u8    l_i_fsize;    /* Fragment size */
            __u16    i_pad1;
            __le16    l_i_uid_high;    /* these 2 fields    */
            __le16    l_i_gid_high;    /* were reserved2[0] */
            __u32    l_i_reserved2;
        } linux2;
        struct {
            __u8    h_i_frag;    /* Fragment number */
            __u8    h_i_fsize;    /* Fragment size */
            __le16    h_i_mode_high;
            __le16    h_i_uid_high;
            __le16    h_i_gid_high;
            __le32    h_i_author;
        } hurd2;
        struct {
            __u8    m_i_frag;    /* Fragment number */
            __u8    m_i_fsize;    /* Fragment size */
            __u16    m_pad1;
            __u32    m_i_reserved2[2];
        } masix2;
    } osd2;                /* OS dependent 2 */
};

索引节点记录了文件的各种属性,如文件大小,文件模式,文件各种时间信息,文件数据块位置信息等。而其中最重要的信息就得数文件数据块位置了。ext2文件系统采用了巧妙的办法来记录文件数据块,兼顾了效率和空间利用率,具体方法如下图所示:

ext2中,将文件的数据块索引组织成数组的形式。在ext2的索引结构中有一个i_block[],该数组共有15项,每项记录的都是物理磁盘块号,其中前12项记录的是一级索引,即该该索引记录的是文件数据块地址,因此,对于小于12个数据块的文件来说,只需要查一次索引即可获得文件数据块位置。i_block[]的第13项是一个二级索引,即其中的块号指向的并不是文件数据块,而是一个存储索引的数据块,该索引数据块中保存了文件数据块的块号,因此,对于大一点的文件,获取数据可能得经历两次索引查询,另外还有三级索引等等,ext2就是采取这种策略来组织文件数据,这种方式在后面的博客中还会有专门的篇幅来阐述,这里点到为止。

ext2元数据结构

时间: 2024-10-10 18:06:51

ext2元数据结构的相关文章

OAF_OAF页面元数据结构MDS的解析(概念)

2014-06-06 BaoXinjian 一.摘要 在OAF编译文件时,系统会通过XMLImport将所编译的XML文件,编译到数据库中,也就是MDS(Meta data Service),元数据库 而在OAF在展现给用户时,系统将存放MDS的内容,再通过程式组合成XML页面定义文件,并进行渲染 所以MDS可以存放了OAF页面的定义,所以二次开发时,在编译XML文件后,并不需要XML文件存放在服务器上 这个和Form Builder的fmx 和 fmb文件有类似性,fmx为编译后的问题,fmb

第126讲:Hadoop集群管理之Datanode目录元数据结构详解学习笔记

namenode是管理hdfs文件系统的元数据 datanode是负责当前节点上的数据的管理,具体目录内容是在初始阶段自动创建的.在用hdfs dfs namenode format时并没有对datanode进行format. 在datanode中目录是按文件信息存储的. datanode存在于具体节点上的hadoop-2.6.0/dfs/data/current中. datanode的VERSION内容与namenode的VERSION内容相似. storageID:在namenode与dat

一个相对通用的JSON响应结构,其中包含两部分:元数据与返回值

定义一个相对通用的JSON响应结构,其中包含两部分:元数据与返回值,其中,元数据表示操作是否成功与返回值消息等,返回值对应服务端方法所返回的数据. public class Response { private static final String OK = "ok"; private static final String ERROR = "error"; private Meta meta; private Object data; public Respon

什么是“元数据”

作者:贺易之链接:https://www.zhihu.com/question/20679872/answer/65565699来源:知乎著作权归作者所有,转载请联系作者获得授权. 要理解这个问题,首先要知道“元”是什么.元(meta),一般被我们翻译成“关于……的……”.事实上,这个前缀来源于希腊文,表示“在……之后”,在某样事情结束之后,就含有了“归纳”.“总结”的意思呢?因此,元,就代表着“本原”.“体系”的意思.以文学领域为例,后现代主义文学中有一种小说叫作“元小说”,也就是“关于小说的

2015第27周一非结构化数据

非结构化数据包括以下几个类型: 文本:在掌握了元数据结构时,机器生成的数据,如传感器等就一定能够进行解译.当然,流数据中有一些字段需要更加高级的分析和发掘功能. 交互数据:这里指的是社交网络中的数据,大量的业务价值隐藏其中.人们表达对人.产品的看法和观点,并以文本字段的方式存储.为了自动分析这部分数据,我们需要借助实体识别以及语义分析等技术.你需要将文本数据以实体集合的形式展现,并结合其中的关系属性. 图像:图像识别算法已经逐渐成为了主流.此外,这些技术也会产生实体,尽管获取关系以及舆情分析更加

ASP.NET MVC Model元数据(四)

ASP.NET MVC Model元数据(四) 前言 前面的篇幅讲解了Model元数据生成的过程,并没有对Model元数据生成过程的内部和Model元数据结构的详细解释.看完本篇后将会对Model元数据有更清楚的了解,当然了也不会是特别全面的,因为后面还有篇幅.希望能给大家带来好的效果. Model元数据 什么是Model元数据? 生成Model元数据的过程[一] 生成Model元数据的过程[二] ModelMetaData的定义.详解 Model元数据应用(常用特性应用)-1 Model元数据

ORACLE AUTOMATIC STORAGE MANAGEMENT翻译-第十章ASM内置数据结构(3)完

Disk Directory Disk Directory包含了磁盘组中所有的磁盘信息.Disk Directory信息比PST更为详细.磁盘组中的每一块盘都有一个条目以数字为索引.Disk Directory的文件号在每个磁盘组中都是2号(F2). Disk Directory中的字段如下: n  Disk name n  Failure group name n  Disk size n  Disk free space n  Disk creation time Disk Director

基础知识漫谈(4):讲讲元数据

说几个风马牛不相及的词儿,spring的依赖注入定义,hibernate的数据映射定义,XML的DTD,再就是我们常说的报文格式. 如果对它们不甚了解,请参考章节一<想到哪儿写到哪儿>.有了基本的了解之后,应当隐约之中有一种感觉,“它们很相似”. 本篇文章要说的就是这个相似性,我管它叫做数据格式\元数据,DataSchema\MetaData.当然,元数据的定义是要大于数据格式的,本文将它们当成同一个概念. 什么是数据格式?看看这段XML(1): <Bean type=”com.nlo.

【转】MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)

MEF中使用导出与导入,实质上就是对一个对象的实例化的过程,通过MEF的特性降低了对象的直接依赖,从而让系统的设计达到一种高灵活.高扩展性的效果.在具体的设计开发中,存在着某些对象是不需要在系统运行或者的附属对象初始化的时候进行实例化的,仅仅只需要在需要使用到他的时候才会进行实例化,从系统的上来说这也是提高系统性能的一种可行的实现方式,这种方式就可以理解为对象的迟延初始化,或者叫迟延加载.MEF也对此使用场景提供了完善的实现机制,下面来看看在MEF中的迟延初始化是如何使用的. namespace