mildcwen

Linux ext2文件系统之初步思考

 


 

数据存放在磁盘中,磁盘最小存取单位sector(512Byte);文件系统中存储的最小单位是 块(Block),大小通常(1KB,2KB,4KB...),

一个block对应多个sector,因而可用block逻辑上 分割 物理磁盘。

通常文件除了 其内部数据外,还有一些属性需要记录。如 权限,大小等, 即 metadata,

将metadata存放在一个叫 inode 中,而数据data则放在block中,(当然 ,inode本身也是存放在块中),于是一个文件对应了一个inode,现在将inode与block关联起来。

1,索引式,inode存放所有block的索引

2, 链接式 ,  inode存放首个block,然后每个block指向其下一个

至于目录,与普通文件相同,只是目录的内容是目录项,它应包含 该目录所有文件(含目录)名,及其inode的索引,方便我们能找到对应文件。

此外,为了对Block和inode进行管理,分配。还有个bitmap位图用与标识一个Block有无被使用.


 

Ext2文件系统

ext2文件系统结构如图:

 

说明:(此信息从外部复制引用,用背景色标注...以上图片也是拷贝的)

一、超级块(Super block):
 描述整个分区的文件系统信息。
1、block与inode总量;
2、未使用与已使用的inode、block数量;
3、block与inode的大小; inode为128 Byte, block 大小格式化时指定
4、文件系统的挂载时间、最近一次写入数据的时间,最近一次检验磁盘的时间等文件系统的相关信息;
5、一个validbit数值,若此文件系统已挂载,则validbit为0,若未挂载,则validbit为1;

一般来说, superblock 的大小为 1024bytes。相关的 superblock 信息我们可以dumpe2fs 命令来呼叫出来观察!

超级块在每个块组的开头都有一份拷贝。事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock ,

而若含则是第一个 block group 内 superblock 的备份,这样可以进行 superblock 的救援!

二、组描述符表(GDT,Group Descriptor Table):

由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符(Group Descriptor)存储一个块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等。和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝。通常内核只用到第0个块组中的拷贝,当执行e2fsck检查文件系统一致性时,第0个块组中的超级块和块组描述符表就会拷贝到其它块组,这样当第0个块组的开头意外损坏时就可以用其它拷贝来恢复,从而减少损失。

 

三、位图 (bitmap) :

其中每个bit表示一个inode/Block是否空闲可用。

 

 

测试及思考:

mke2fs时通过 -b 指定blocksize,从而得到 block count.

通常用 -i 来得到 inode count ,其参数 字节/inode,就是每?字节一个inode,通常设为block size 倍数.

(说明: B→block size,Gnum→group count,Bnum→block count,Inum→inode count)

1).因为每个group中用一个B来表示位图,所以一个group中最多8*B个数据块,因而ext2的group分配策略是:每个group大小为8*B (单位:块),

那么 gnum=bnum/8*B,每个组的inode count=inum/gnum,从而得出 inode表占用block的数量

现在需确定 GDT占用 block数,剩下的则都是用于数据块了。而根据dumpe2fs显示结果看,GDT也是固定的,还有 保留的GDT块。这不理解怎么分配的。

另外,只有前两个group有超级块和GDT....

因而每个组中各个数据的偏移位置也就能确定了。从而能根据给定一个 inode idx或 data idx找到其对应group的对应block !!(即找到读写位置)

 

2).我测试时用dumpe2fs 显示的inode size总是256,而不是128,建的也是ext2,不知道为什么.

而first inode总是11,(刚格式化未建立任何文件).

我能理解的是,为了能正常访问FS中的数据,我需要预先创建一个/根目录,之后的所有新建的文件都在这其下。

也就是标记一个BLOCK作为入口,那么刚格式化时占用一个inode我能理解,为何11个?还需要作什么?

 

3).inode table中,每个inode size 为128字节,其中 最后60字节用于索引 数据块,15个(12直接,一次,一级,二级……)每个4字节用于指定 block id.

      4字节 unsigned 32,可标识 232 =4*G个block,也就是说最多能用于 4*G*B个字节的FS,而ext2有相应的最大系统总容量限制,都没有超过这个。

 

4)目录在文件系统中具体如何存储?

存储的应是 文件名+inode id,

文件名linux限制最长255,应该是用NUL作结束标志,占256字节。那么inode id用多长来标识?

若定长,则一个块只能放几个目录,测试了下,很明显不是。

所以 ,若不定长,用NUL标识文件名结束,再加一个定长Id,但这样的话,不能……

突然又意识到 ,在磁盘中读取目录内容不正是要读出所有 么。所以递归遍历刚好!!

那么 inode用多长来标识?首先inode count必然小于 block count,所以,还是用4字节标识把,应该...

 

5). 读取文件系统时,需要先 从入口 /进入,查看其内容,得到子目录列表,然后依次 往下……

直到遍历到所需为止。e.g.如果我要打开文件系统某个文件,我得从根目录开始依次读取下去,直到找到该文件inode,然后再打开。。

这涉及多次读取磁盘,如果目录深度够深,结果 可想....

我之所以会如此思考,是因为,文件系统应独立于OS!

所幸,Linux有其目录系统。从/开始。每个目录或文件,绑定了 inode,先跳转下思路,

当我挂载某个文件系统时,此时,就会遍历该FS整个目录结构,并记录下。续接到其挂载目录之下。

其中包含文件名和inode,因为inode只能用与其本身的文件系统,所以目录树还应包含挂载到目录上的FS,子目录默认继承父目录。

这样我们指定一个path时就能通过目录树,快速找到其所在文件系统,以及inode,从而进行读写.

我想,这也是linux需要 挂载的理由 把------为了生成目录树,(根目录/也有挂载的分区的),方便读写。

顺便一提,ls命令中的文件类型我猜测也是保存于目录树上的。

 

posted on 2017-11-08 17:51  mildcwen  阅读(225)  评论(0编辑  收藏  举报

导航