从演进模型的视角来看ext2

以下是个人的见解,不一定对.只是说这样的视角去看ext2比较习惯.
概括来讲:就是ino作为索引号,坚持并一致的用数组寻址来实现高效率.

# ext2模型1.0#

磁盘是块设备,是按扇区块来访问.固定大小为512byte.
这个512byte是固定的,我们灵活一下.在上面再建一层弹性大小的粒度.形成更大的小格子来管理.
也就是块block(blk缩写).所有的数据按块对齐align管理.
把整块磁盘划是一个个可设置粒度大小的小格子来管理.
事实上并不是1,2,3,..N个扇区来,而是按2^x指数大小来块.这是有好处的.
这个背后其实基数树思想有关系,是实现基址与偏移方案的基础.倒不是最省存储资源的方案.因为有浪费.

[blk 1][blk2]...[blkN]



# ext2模型1.1 #
把数据放在小格子里.然后怎么找对应的内容?也就是从inode号查找inode的内容是什么方式比较有效率.
最有效率的是用数组O[1]的理论效率.

inode meta元数据组成一维数据,从inode number直接寻址到对应的inode meta元数据.
inode meta元数据记录inode内容在哪.

示意简图
[inode meta data array n个blk ][data  m个blk]

怎么知道[inode meta data array]有多长,[data]起始在哪?
需要一个额外的数据来记录这些信息.

# ext2模型1.2 #
super_block就是记录ext2模型1.0这些额外的信息用的,解决1.1的问题.

示意简图
[super_block 1个blk][inode meta data array n个blk][data m个blk]

简洁,高效.
有啥问题?有2层问题.
1.如果文件删除,创建,再删除.怎么办?
2.如果文件内容,修改,删除,怎么办?


# ext2模型1.3 #

模型1.2只创建是没有问题的.为了支持删除,再创建.
首先的问题在于怎么管理空闲的inode number号.
其次的管理块的使用,空闲信息.
ext2模型1.3还是用数组来解决,只是这次用位图bitmap.节约存储资源.
分别采用bit为1表示使用,空闲则为0.
对应的分别是[inode bitmap][blk bitmap]

示意简图
[super_block][blk bitmap][inode bitmap][inode meta data array][data]

看起来完美了.一个文件系统原型在功能上没有问题了.


# ext2模型1.4#

继续优化.一个文件很大,也可能很小.怎么才能有效率的动态适应这个弹性.
基数树radix tree能动态的按需生长.和内存的页表是一样的原理.
ext2_1.4[15] 对于大量的小文件直接放12个blk来存取.至少能存下12KB.对于很多小文件是够大的.

ext2_1.4[1-12] direct blk number
ext2_1.4[13] indirect blk number
ext2_1.4[14] double indirect blk number
ext2_1.4[15] triple indirect blk number
这个方案再用4阶基数树,来适应不同大小的文件.是相当的精彩的方案.


# ext2模型1.5#
继续优化,这次的优化怎么讲了.说有必要吧.好像也没有.
说没有,好像有点适应机械磁盘的意思.
基本思想是,把1.4当成一个组,整个磁盘划成N个这个的块组.尽量局部访问.不让磁头满盘跑.另外
带来了冗余,在崩溃的能有备份.其它冗余备份也不用这样搞呀.对比FAT,人家就没有用分块组.
于是添加了块组描述.老套路,还是用数组.

单个块组示意简图
[super_block][blk group desc][blk bitmap][inode bitmap][inode meta data array][data]
磁盘示意简图
[boot blk][blk group 0][blk group 1]...[blk group N]

到此基本上就是ext2的最终实现方案.

# 分析一下小细节 #
Q1:怎么通过ino找到对应的文件内容?
首先super_block记录了blk_per_group,inode_per_group,first_ino.
先找在哪个块组里. group_index=(ino-frist_ino)/inode_per_group.知道在第几个块组中.
通过块组描述找到对应的块组位置.
然后在对应块组里找到对应的inode meta data index=(ino-frist_ino)%inode_per_group
通过这个index找到对应的inode meta data.这个inode meta data有数据blk信息.over.

Q2:inode_per_group是怎么订的?
对于blk_per_group无异是一个blk所有bit管理.但是这个inode_per_group就很怪了.
因为inode mata data array要占用资源,所以它做了个平衡,不耗尽所有的bit map.这个是文件系统
创建时指定的.
4KB blk size 时blk_per_group是32K,但是inode_per_group可能就是7K.

Q3:目录项的方案如何?怎么关联ino?
目录项是采用不定长方案.紧凑.其中就有ino这个数据.还有个名字.
 


一点小实践操作

格式化一个1GB的U盘,好吧其实是张SD卡.

 sudo mke2fs /dev/sdc1
[sudo] password for q: 
mke2fs 1.42 (29-Nov-2011)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
60544 inodes, 241903 blocks
12095 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=251658240
8 block groups
32768 blocks per group, 32768 fragments per group
7568 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376

用磁盘编辑器打开,看下super block信息是否与定义对得上.

struct ext2_super_block {
    __le32    s_inodes_count;        /* Inodes count */
    __le32    s_blocks_count;        /* Blocks count */
    __le32    s_r_blocks_count;    /* Reserved blocks count */
    __le32    s_free_blocks_count;    /* Free blocks count */
    __le32    s_free_inodes_count;    /* Free inodes count */
    __le32    s_first_data_block;    /* First Data Block */
    __le32    s_log_block_size;    /* Block size */
    __le32    s_log_frag_size;    /* Fragment size */
    __le32    s_blocks_per_group;    /* # Blocks per group */
    __le32    s_frags_per_group;    /* # Fragments per group */
    __le32    s_inodes_per_group;    /* # Inodes per group */

s_inodes_count:0000ec80 = 60544   s_blocks_count:0003b0EF= 241903

s_blocks_per_group:00008000=32768  s_inodes_per_group:00001d90=7568

与格式化输出信息是一致的!


转载请说明出处,谢谢

猜你喜欢

转载自blog.csdn.net/pcj2007/article/details/81476322