IT技术互动交流平台

Linux服务器存储文件系统之ext2【下】

作者:wjlkoorey258  发布日期:2013-01-16 11:16:06
Linux服务器存储文件系统之ext2【上】

     今天我们来认识一下superblock,inode,block,group,group descriptor,block bitmap,inode table这些家伙。为什么在上一篇博文开篇没详细介绍这些概念呢,因为任何关于文件系统的文章还是书籍一开始都是先说概念、说理论,让人一直有种雾里看花的感觉。纸上得来终觉浅,事必躬亲才印象深,所以我们以一块实际硬盘为例(当然是虚拟出来的,呵呵)来向大家展示了一下文件系统在存储介质上的布局情况,先让大家对其有个比较直观的认识,然后再逐一对它们进行解释和说明,印象会更深刻些。咱不否认理论的重要性,秉承着“理论指导实践,以实践加深对理论的认识”的宗旨来一步一步入文件系统的乐园。


superblock
     这个东西确实很重要,前面我们已经见识过。为此,文件系统还特意精挑细选的找了N多后备Group,在这些Group中都存有superblock的副本,你就知道它有多重要了。说白了,superblock 的作用就是记录文件系统的类型、block大小、block总数、inode大小、inode总数、group的总数等等。
group descriptors
     千万不要以为这就是一个组描述符,看到descriptor后面加了个s就知道这是N多描述符的集合。确实,这是文件系统中所有group的描述符所构成的一个数组,它的结构定义在include/linux/ext2_fs.h中:

/* 
 * Structure of a blocks group descriptor 
 */ 
struct ext2_group_desc 
{ 
         __le32      bg_block_bitmap;             /* group中block bitmap所在的第一个block号 */ 
         __le32      bg_inode_bitmap;            /* group中inode bitmap 所在的第一个block号 */ 
         __le32      bg_inode_table;                /* group中inodes table 所在的第一个block号 */ 
         __le16      bg_free_blocks_count;    /* group中空闲的block总数 */ 
         __le16      bg_free_inodes_count;   /* group中空闲的inode总数*/ 
         __le16      bg_used_dirs_count;       /* 目录数 */ 
         __le16      bg_pad; 
         __le32      bg_reserved[3]; 
};

下面的程序可以帮助了解一下/dev/hdd1中所有group的descriptor的详情:

 

[root@localhost cu]# cat grp_dsp.c 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <string.h> 
#include <linux/ext2_fs.h> 
  
#define B_LEN 32  //一个struct ext2_group_desc{}占固定32字节 
  
int main(int argc,char** argv){ 
    char buf[B_LEN] = {0}; 
    int i=0,fd = -1; 
    struct ext2_group_desc gd; 
    memset(&gd,0,B_LEN); 
  
    if(-1 == (fd=open(argv[1],O_RDONLY,0777))){ 
        printf("open file error!n"); 
        return 1; 
    } 
  
    while(i<64){    //因为我已经知道了/dev/hdd1中只有64个group 
        if(-1 == read(fd,buf,B_LEN)){ 
            printf("read error!n"); 
            close(fd); 
            return 1; 
        } 
        memcpy((char*)&gd,buf,B_LEN); 
        printf("========== Group %d: ==========n",i); 
        printf("Blocks bitmap block %ld n",gd.bg_block_bitmap); 
        printf("Inodes bitmap block %ld n",gd.bg_inode_bitmap); 
        printf("Inodes table block %ld n",gd.bg_inode_table); 
        printf("Free blocks count %d n",gd.bg_free_blocks_count); 
        printf("Free inodes count %d n",gd.bg_free_inodes_count); 
        printf("Directories count %d n",gd.bg_used_dirs_count); 
  
        memset(buf,0,B_LEN); 
        i++; 
    } 
  
    close(fd); 
    return 0; 
}

     运行结果和dumpe2fs /dev/hdd1的输出对比如下:

     其中,文件gp0decp是由命令“dd if=/dev/hdd1 of=./gp0decp bs=4096 skip=1 count=1”生成。每个group descriptor里记录了该group中的inode table的起始block号,因为inode table有可能会占用连续的多个block;空闲的block、inode数等等。




inode table:
     在文件系统中每个对象都有一个对应的inode节点(这句话有些不太准确,因为符号链接和它的目标文件共用一个inode),里存储了一个对象(文件或目录)的信息有权限、所占字节数、创建时间、修改时间、链接数、属主ID、组ID,如果是文件的话还会包含文件内容占用的block总数以及block号。inode是从1编号,这一点不同于block,需要格外注意。另外,/dev/hdd1是新挂载的硬盘,格式化成ext2后并没有任何数据,只有一个lost+found目录。接下来我们用命令“dd if=/dev/hdd1 of=./gp0 bs=4096 count=32768”将Group0里的所有数据提取出来。
     前面已经了解了Group0的一些基本信息如下: www.it165.net

 

Group 0: (Blocks 0-32767) 
  Primary superblock at 0, Group descriptors at 1-1 
  Reserved GDT blocks at 2-512 
  Block bitmap at 513 (+513), Inode bitmap at 514 (+514) 
  Inode table at 515-1026 (+515) 
  31739 free blocks, 16374 free inodes, 1 directories       #包含一个目录 
  Free blocks: 1028-1031, 1033-32767                          #一共有31739个空闲block 
  Free inodes: 11-16384                                                 #一共有16374个空闲inode


     block bitmap中每个bit表示一个block的占用情况,0表示对应的block为空,为1表示相应的block中存有数据。在/dev/hdd1中,一个group里最多只能包含8×4096=32768个block,这一点我们已经清楚了。接下来我们来看一下Group0的block bitmap,如下:


 



     发现block bitmap的前128字节和第129字节的低4位都为1,说明发现Group0中前128×8+4=1028个block,即block0~block1027都已被使用了。第129字节的高4位为0,表示block1028~block1031四个block是空闲的;第130字节的最低位是1,说明block1032被占用了;从block1033~block32767的block bitmap都是0,所以这些block都是空闲的,和上表输出的结果一致。
 
inode bitmap:
     和block bitmap类似,每个比特表示相应的inode是否被使用。Group0的inode bitmap如下:
 



      /dev/hdd1里inode总数为1048576,要被均分到64个Group里,所以每个Group中都包含了16384个inode。要表示每个Group中16384个inode,inode bitmap总共需要使用2048(16384/8)字节。inode bitmap本身就占据了一个block,所以它只用到了该block中的前2048个字节,剩下的2048字节都被填充成1,如上图所示。
     我们可以看到Group0中的inode bitmap前两个字节分别是ff和03,说明Group0里的前11个inode已经被使用了。其中前10个inode被ext2预留起来,第11个inode就是lost+found目录,如下:



inode table:
     那么每个Group中的所有inode到底存放在哪里呢?答案就是inode table。它是每个Group中所有inode的聚合地。
因为一个inode占128字节,所以每个Group里的所有inode共占16384×128=2097152字节,总共消耗了512个block。Group的group descriptor里记录了inode table的所占block的起始号,所以就可以唯一确定每个Group里inode table所在的block的起始号和结束号了。inode的结构如下:

 



     这里我们主要关注的其中的数据block指针部分。前12个block指针直接指向了存有数据的block号;第13个block指针所指向的block中存储的并不是数据而是由其他block号,这些block号所对应的block里存储的才是真正的数据,即所谓的两级block指针;第14个block为三级block指针;第15个block为四级block指针。最后效果图如下:
 




     一个block为4096字节,每个块指针4字节,所以一个block里最多可以容纳4096/4=1024个block指针,我们可以计算出一个inode最大能表示的单个文件的最大容量如下:



直接block指针(字节) 两级block指针(字节) 三级block指针(字节) 四级block指针(字节) 单个文件的最大容量(字节)
12×409 4096/4×4096 40962/4×4096 40963/4×4096 4TB

     所以,我们可以得出不同block大小,对单个文件最大容量的影响。假设block大小为X字节,则:



     如下表所示:



block大小(字节) 单个文件容量(字节)
1024 17247240192字节(16GB)
2048 275415826432字节(256GB)
4096 4402345672704字节(4TB)
 
   最后来一张全家福:


       完。
 

Tag标签: Linux   服务器存储   存储文件系统  
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规