9.2.3  Ext2的索引节点

Ext2Unix类的文件系统一样,使用索引节点来记录文件信息。每一个普通文件目录都有唯一的索引节点与之对应,索引节点中含有文件或目录的重要信息。当你要访问一个文件或目录时,通过文件或目录名首先找到与之对应的索引节点,然后通过索引节点得到文件或目录的信息及磁盘上的具体的存储位置。Ext2的索引节点的数据结构叫ext2_inode,在include/Linux/ext2_fs.h中定义,下面是其结构及各个域的含义。(不同版本,该结构略有不同)。

struct ext2_inode {   

    __u16  i_mode;     /* 文件类型和访问权限 */

   __u16   i_uid;      /* 文件拥有者标识号*/

   __u32   i_size;     /* 以字节计的文件大小 */

   __u32   i_atime;    /* 文件的最后一次访问时间 */

   __u32   i_ctime;    /* 该节点最后被修改时间 */

   __u32   i_mtime;    /* 文件内容的最后修改时间 */

   __u32   i_dtime;    /* 文件删除时间 */

   __u16   i_gid;      /* 文件的用户组标志 */

   __u16   i_links_count;  /* 文件的硬链接计数 */

   __u32   i_blocks;     /* 文件所占块数(每块以512字节计)*/

   __u32   i_flags;         /* 打开文件的方式 */

   union                    /*特定操作系统的信息*/

  __u32 i_block[Ext2_N_BLOCKS];      /* 指向数据块的指针数组 */

   __u32   i_version;                /* 文件的版本号(用于 NFS */

   __u32   i_file_acl;                 /*文件访问控制表(已不再使用) */

   __u32   i_dir_acl;                 /*目录 访问控制表(已不再使用)*/

    __u8   l_i_frag;                   /* 每块中的片数 */

    __u32   i_faddr;                   /* 片的地址 */

    union                            /*特定操作系统信息*/

}

从中可以看出,索引节点是用来描述文件或目录信息的。

以下,对其中一些域作一定解释。

1)前面说过,Ext2通过索引节点中的数据块指针数组进行逻辑块到物理块的映射。在Ext2索引节点中,数据块指针数组共有15项,前12个为直接块指针,后三个分别为“一次间接块指针”、“二次间接块指针”、“三次间接块指针”,如图9.4所示。

         
9.4   索引节点的数据块指针数组示意图

所谓“直接块”,是指该块直接用来存储文件的数据,而“一次间接块”是指该块不存储数据,而是存储直接块的地址,同样,“二次间接块”存储的是“一次间接块”的地址。这里的所说的块,指的都是物理块。Ext2默认的物理块大小为1K,块地址占4个字节(32位),所以每个物理块可以存储256个地址。这样,文件大小最大可达12K+256K+64M+16G。但实际上,Linux32位的操作系统,故文件大小最大只能为4G

系统是以逻辑块号为索引查找物理块的。例如,要找到第100个逻辑块对应的物理块,因为256+12>100>12,所以要用到一次间接块,在一次间接块中查找第88项,此项内容就是对应的物理块的地址。而如果要找第1000个逻辑块对应的物理块,由于1000>256+12,所以要用到二次间接块了。

2)索引节点的标志(flags)取下列几个值的可能组合。

EXT2_SECRM_FL   0x00000001

完全删除标志。设置这个标志后,删除文件时,随机数据会填充原来的数据块。

EXT2_UNRM_FL    0x00000002

可恢复标志。设置这个标志后,删除文件时,文件系统会保留足够信息,以确保文件仍能恢复(仅在一段时间内)

EXT2_COMR_FL  0x00000004

压缩标志。设置这个标志后,表明该文件被压缩过。当访问该文件时,文件系统必须采用解压缩算法进行解压。

EXT2_SYNC_FL  0x00000008

同步更新标志。设置该标志后,则该文件必须和内存中的内容保持一致,对这种文件进行异步输入、输出操作是不允许的。这个标志仅用于节点本身和间接块。数据块总是异步写入磁盘的。

除了这几个常用标志外,还有12个标志就不一介绍了。

3)索引节点在磁盘上是经过编号的。其中,有一些节点有特殊用途,用户不能使用。这些特殊节点也在include/Linux/ext2_fs.h中定义。

#define EXT2_BAD_INO           1

该节点所对应的文件中包含着该文件系统中坏块的链接表

 

#define EXT2_ROOT_INO         2

该文件系统的根目录所对应的节点

 

#define EXT2_IDX_INO            3

ACL(访问控制链表)节点

 

#define EXT2_DATA_INO         4

ACL节点

 

#define EXT2_BOOT_LOADER_INO       5

用于引导系统的文件所对应的节点

 

#define EXT2_UNDEL_DIR_INO              6

文件系统中可恢复的目录对应的节点

 

没有特殊用途的第一个节点号为11

#define  EXT2_FIRST_INO                   11

 

4)文件的类型、访问权限、用户标识号、用户组标识号等将在后面介绍。

 

Ext2超级块类似,当磁盘上的索引节点调入内存后,除了要填写VFS的索引节点外,系统还要根据它填写另一个数据结构,该结构叫ext2_inode_info,其作用也是为了存储特定文件系统自己的特性,它在include/Linux/ext2_fs_i.h中定义如下:

struct ext2_inode_info

{

   __u32   i_data[15];               /*数据块指针数组*/

   __u32   i_flags;                   /*打开文件的方式*/

   __u32   i_faddr;                   /*片的地址*/

   __u8    i_frag_no;                 /*如果用到片,则是第一个片号*/

   __u8    i_frag_size;               /*片大小*/

      __u16   i_osync;                    *同步*/

   __u32   i_file_acl;                /*文件访问控制链表*/

   __u32   i_dir_acl;                  /*目录访问控制链表*/

   __u32   i_dtime;                    /*文件的删除时间*/

   __u32   i_block_group;              /*索引节点所在的块组号*/

/******以下四个域是用于操作预分配块的*************/

   __u32   i_next_alloc_block;          

   __u32   i_next_alloc_goal;

   __u32   i_prealloc_block;

   __u32   i_prealloc_count;

 

  __u32   i_dir_start_lookup

    int     i_new_inode:1   /* Is a freshly allocated inode */

};

 

VFS索引节点中是没有物理块指针数组的域,这个Ext2特有的域在调入内存后,就必须保存在ext2_inode_info 这个结构中。此外,片作为Ext2比较特殊的地方,在ext2_inode_info 中也保存了一些相关的域。另外,Ext2在分配一个块时通常还要预分配几个连续的块,因为它判断这些块很可能将要被访问,所以采用预分配的策略可以减少磁头的寻道时间。这些用于预分配操作的域也被保存在ext2_inode_info结构中。