ITPub博客

首页 > Linux操作系统 > Linux操作系统 > LINUX 的EXT2文件系统的组织方式

LINUX 的EXT2文件系统的组织方式

原创 Linux操作系统 作者:gaopengtttt 时间:2016-01-25 12:56:06 0 删除 编辑
LINUX 的EXT2文件系统学习理解


文件系统的构架非常复杂,在学习中使用了EXT2进行分析和学习,EXT3,EXT4虽然有改进但是基本原理一致
结合学习的东西必须记录一下。


磁盘的块分布情况,默认的我们的一个块是4K,在磁盘中块被划分成成组的形式。记为GROUP 0-GROUP N。
使用dumpe2fs 命令可以看到block group的使用情况。

块的组织方式:

磁盘第一个块:启动块 (boot block)
组0:(假设I个块)
组第一个块:超级块 (SUPER BLOCK)
组第二到第N个块:块组描述符表(GDT)
组第N+1个块:块位图块(block bit map)
组第N+2个块:Inode 位图块(Inode bit map block)
组第N+3到M个块:Inode 表块 (Inode table block)
组第M+1个块到I个块:data block 

组1:也是如组0进行组织
组2:也是如组0进行组织
....
组N:也是如组0进行组织


接下来我们进行每个块的分开讨论:
1、启动块 (boot block):这是一个磁盘只有一个的块用来记录磁盘的分区和启动信息,这是不归入文件系统的一个块
2、超级块 (SUPER BLOCK):
描述整个分区的文件系统信息,例如块大小、文件系统版本号、上次mount的时间等等。超级块在每个块组的开头都有一份拷贝。
3、块组描述符表(GDT):每个块组描述符(Group Descriptor)存储一个
块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的
inode和数据块还有多少个等等。和超级块类似,块组描述符表在每个块组的开头也都有一
份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组
描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝
4、块位图块(block bit map):
这里面的一位表示了块是否可用,没有使用记为0,使用了标记为1,考虑到这里ORACLE 11G的
一个数据文件的前128个块也是用于这个作用,而这里如果一个块为4K,那么一个块一共有
4096*8=32768个bit位,那么也就算出来一个组的最大大小为 32768*4096。使用dumpe2fs /sda1
也能有这样的显示:
Block size:               4096  
Blocks per group:         32768 
5、Inode 位图块(Inode bit map block):
同样为Inode的使用情况,没有使用记为0,使用了标记为1,同样也是占用一个块。如果通过计算发现
4096*8=32768个位是用不完的。见后面INODE分析
6、Inode 表块 (Inode table block)
每个文件都有一个Inode,而这些Inode记录实际是记录在Inode表中的,形成一行一行的Inode记录
Inode用于记录文件的基本信息,而不是文件真正的数据信息,如下:
root@bogon:~# stat log.log
  File: ‘log.log’
  Size: 35848           Blocks: 72         IO Block: 4096   regular file
Device: 801h/2049d      Inode: 1332077     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-01-17 21:31:00.359863946 +0800
Modify: 2016-01-17 21:30:56.995864067 +0800
Change: 2016-01-17 21:30:56.995864067 +0800
Birth: -
可以看到这里信息非常多,
例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访
问时间等 ,这其实在内核中是一个数据结构。
 23 struct stat {
 24     unsigned long   st_dev;     /* Device.  */
 25     unsigned long   st_ino;     /* File serial number.  */
 26     unsigned int    st_mode;    /* File mode.  */
 27     unsigned int    st_nlink;   /* Link count.  */
 28     unsigned int    st_uid;     /* User ID of the file's owner.  */
 29     unsigned int    st_gid;     /* Group ID of the file's group. */
 30     unsigned long   st_rdev;    /* Device number, if device.  */
 31     unsigned long   __pad1;
 32     long        st_size;    /* Size of file, in bytes.  */
 33     int     st_blksize; /* Optimal block size for I/O.  */
 34     int     __pad2;
 35     long        st_blocks;  /* Number 512-byte blocks allocated. */
 36     long        st_atime;   /* Time of last access.  */
 37     unsigned long   st_atime_nsec;
 38     long        st_mtime;   /* Time of last modification.  */
 39     unsigned long   st_mtime_nsec;
 40     long        st_ctime;   /* Time of last status change.  */
 41     unsigned long   st_ctime_nsec;
 42     unsigned int    __unused4;
 43     unsigned int    __unused5;
 44 };

除了记录这些结构数据,剩下就是指向数据块的指针一个指针为4BYTES,每个文件的inode的索引项一共有15 个,
从 Blocks[0] 到Blocks[14],0-11个块指针可以直接指向数据块,叫做直接寻址,而第12个块指针指向的实际是一个新的指针
块,那么如果一个块为4K那么这个块又可以指向4096/4=1024个块,这叫一级寻址这样一级寻址能够建立的最大文件
为11*4+1024*4 这样就上MB了,如果这样还不够还有 13 指针还可以使用二级寻址,甚至还有14号指针使用三级寻址,
如果启用三级寻址那么最大文件大小是:11*4+1024*4+1024*4096/4+1024*4096/4*4096/4=44+4096+1048576+1073741824=1074794540 个块
如果算上4K 1074794540*4/1024/1024~4T。

在格式化的时候INODE就进行了分配,那么一个GROUP到底分配多少个INODE合适呢,LINUX用一个小文件来
默认的操作系统认为一个文件为8K,那么如果一个group有多少个8K就分配多少个INODE,
这样算下:
32768*4/8=16384 个Inode
查看

Inodes per group:         16384 
Inode blocks per group:   512

但是我查看新的Ubuntu 14.04.3 中这个改变了
Inodes per group:         8192
Inode blocks per group:   512


那么我们很容易的算出 这个他认为文件为16K,那么也就是说,如果大量的文件小于16K那么会出现 Inode耗尽的情况,
如果是以前是如果大量的文件小于8k。

理论上rm 一个文件只是将他的block bit map,inode bit map进行反转为0同时可能的释放指针指向的数据块,实际数据并没有真正删除,所以删除非常快,这个和数据库中的DROP有一样的原理。



除此以外我们需要理解我们的目录
目录实际上也是一个需要一个inode的文件,而初始Inode指向一个数据库为4096,同样他的各种信息
如例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访
问时间等 
如下:
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 801h/2049d      Inode: 1330599     Links: 2
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-01-19 12:19:56.896204445 +0800
Modify: 2016-01-16 13:56:06.586658881 +0800
Change: 2016-01-16 13:56:06.586658881 +0800


而在这个数据块中存放着关于文件的记录
包含文件名、Inode、记录长度、文件类型,文件名实际数存在目录的记录中的,而他又包含了Inode。


大家都知道在文件系统中都有一个/ 根目录,这个/ 目录的Inode固定而2,这样我们就能找到/目录的数据块,然后就能
进行依次定位了,比如我们方位/home/oracle/log.log文件那么找到log.log文件的次序如下:
1、先找到inode 2,然后通过 Inode 2的数据指针找到/根目录的数据块。
2、在根目录的数据块中寻找到home目录在 /目录数据块中的记录项,其中包含了
   文件名、Inode、记录长度、文件类型
   那么文件名就是HOME ,Inode指向的数据块就是Home目录实际的数据块
3、找到Home目录的数据块,定位ORACLE目录在Home目录数据块的记录项,同样包含
   文件名、Inode、记录长度、文件类型
    那么文件名就是oracle Inode指向的数据块就是oralce目录实际的数据块
4、在ORACLE目录的数据块中找到LOG.LOG的记录项目,同样为
   文件名、Inode、记录长度、文件类型
   文件名为LOG.LOG Inode指向的数据块就是log.log文件实际的数据块
 那么我们归纳一下
 /根目录的Inode 为2------》/根目录的数据块------》找到Home目录的记录项
 --------》通过Inode定位到HOME目录的数据块-----》找到ORACLE目录的记录项
 -------》根据Inode定位到ORACLE目录的数据块-----》找到LOG.LOG文件的记录项目
 ------》根据Inode定位到LOG.LOG的文件块
 如此数据就找到了Inode也找到了
 
 所以我们可以简单的认为目录越深,查找的代价越大

最后记录一下这几个时间
Access: 2016-01-24 19:57:38.228325273 +0800  访问时间
Modify: 2016-01-24 19:56:36.140325137 +0800  修改数据块时间
Change: 2016-01-25 04:56:58.941460486 +0800 修改Inode信息时间,换句话说比如修改了文件权限



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7728585/viewspace-1981902/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
wxh gp_22389860

注册时间:2008-10-13

  • 博文量
    640
  • 访问量
    2818496