怎么认识Ext2文件系统的原理

一.VFS(虚拟文件系统)和Ext2关系:

VFS是Linux中的一个虚拟文件文件系统,它为应用程序员提供一层抽象,屏蔽底层各种文件系统的差异,如图所示

vfs和Ext2文件系统关系

不同的文件系统,如Ext2/3/4、XFS等,具有不同的结构,假如用户调用open等函数去打开文件,具体的实现会非常不同。为了屏蔽这种差异,Linux引入了VFS的概念。相当于是Linux自建了一个新的贮存在内存中的文件系统。所有其他文件系统都需要先转换成VFS的结构才能为用户所调用。(借老师一句话,VFS就相当于联合国,下面的具体文件系统Ext2等就相当于具体国家,很形象)。

二.文件系统的特性

既然ext2文件系统得需要vfs才能被用户空间使用,那么vfs所拥有的特性ext2也会有

那么文件系统是如何运行的呢?这与操作系统的文件数据有关。较新的操作系统的文件数据除了文件实际内容外,通常含有非常多的属性,例如Linux操作系统的文件权限(rwx)与文件属性(拥有者、属组、其他用户等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到inode中,至于实际数据则放置到d数据区中。另外,还有一个超级区块(superblock)会记录整个文件系统的整体信息。

(文件系统的三个区域)

每个inode与block都有编号,至于这三个数据的意义可以简略说明如下:

superblock:记录此filesystem的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;

inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的block号码;

block:实际记录文件的内容,若文件太大时,会占用多个block。

由于每个inode与block都有编号,而每个文件都会占用一个inode,inode内则有文件数据放置的block号码。因此,我们可以知道的是,如果能够找到文件的inode的话,那么自然就会知道这个文件所放置数据的block号码,当然也就能够读出该文件的实际数据了。这是个比较有效率的作法,因为如此一来我们的磁盘就能够在短时间内读取出全部的数据。

我们将inode与block区块用图解来说明一下,如下图所示,文件系统先格式化出inode与block的区块,假设某一个文件的属性与权限数据是放置到inode4号(下图较小方格内),而这个inode记录了文件数据的实际放置点为2,7,13,15这四个block号码,此时我们的操作系统就能够据此来排列磁盘的阅读顺序,可以一口气将四个block内容读出来!那么数据的读取就如同下图中的箭头所指定的模样了。

这种数据存取的方法我们称为索引式文件系统,ext2也属于这样的文件系统,而FAT文件系统并没有inode

三.Linux中的Ext2文件系统

inode的内容记录文件的权限与相关属性,至于block(数据区)则是在记录文件的实际内容。而且文件系统一开始就将inode与block规划好了,否则inode与block固定后就不再变动。但是如果仔细考虑一下,如果我的文件系统很大时,那么将所有的inode与block通通放置在一起将是很不智的决定,因为inode与block的数量太庞大,不容易管理。

因此Ext2文件系统在格式化的时候基本上是区分为多个区块群组(blockgroup)的,每个区块群组都有独立的inode/block/superblock系统。就好像我们在当兵时,一个营里面有分成数个连,每个连有自己的联络系统,但最终都向营部回报连上最正确的信息一样!这样分成一群群的比较好管理啦!整个来说,Ext2格式化后有点像底下这样:

在Ext2.h中对上面的超级块,组描述符、数据块都有定义。文件系统中存储的最小单位是块(Block),一个块究竟多大是在格式化时确定的,格式化时设定块大小为1k、2k或4k字节,这些blocks被聚在一起分成几个大的blockgroup。每个blockgroup中有多少个block是固定的。而上图中启动块(BootBlock)的大小是确定的,就是1KB,启动块是由PC标准规定的,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用启动块。启动块之后才是ext2文件系统的开始,ext2文件系统将整个分区划成若干个同样大小的块组(BlockGroup),每个块组都由以下部分组成

1).超级块(SuperBlock)

描述整个分区的文件系统信息,例如块大小、文件系统版本号、上次mount的时间等等。超级块在每个块组的开头都有一份拷贝。

2).块组描述符表(GDT,GroupDescriptorTable)

由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符(GroupDescriptor)存储一个块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等。和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝。通常内核只用到第0个块组中的拷贝。

3).块位图(BlockBitmap)

一个块组中的块是这样利用的:数据块存储所有文件的数据,比如某个分区的块大小是1024字节,某个文件是2049字节,那么就需要三个数据块来存,即使第三个块只存了一个字节也需要占用一个整块;超级块、块组描述符表、块位图、inode位图、inode表这几部分存储该块组的描述信息。那么如何知道哪些块已经用来存储文件数据或其它描述信息,哪些块仍然空闲可用呢?块位图就是用来描述整个块组中哪些块已用哪些块空闲的,它本身占一个块,其中的每个bit代表本块组中的一个块,这个bit为1表示该块已用,这个bit为0表示该块空闲可用。

为什么用df命令统计整个磁盘的已用空间非常快呢?因为只需要查看每个块组的块位图即可,而不需要搜遍整个分区。相反,用du命令查看一个较大目录的已用空间就非常慢,因为不可避免地要搜遍整个目录的所有文件。

与此相联系的另一个问题是:在格式化一个分区时究竟会划出多少个块组呢?主要的限制在于块位图本身必须只占一个块。格式化时默认块大小是1024字节,可以设定参数指定块大小,现在设块大小指定为b字节,那么一个块可以有8b个bit,这样大小的一个块位图就可以表示8b个块的占用情况,因此一个块组最多可以有8b个块,如果整个分区有s个块,那么就可以有s/(8b)个块组。

4).inode位图(inodeBitmap)

和块位图类似,本身占一个块,其中每个bit表示一个inode是否空闲可用

5).inode表(inodeTable)

我们知道,一个文件除了数据需要存储之外,一些描述信息也需要存储,例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访问时间等,也就是ls-l命令看到的那些信息,这些信息存在inode中而不是数据块中。每个文件都有一个inode,一个块组中的所有inode组成了inode表。

inode表占多少个块在格式化时就要决定并写入块组描述符中,mke2fs格式化工具的默认策略是一个块组有多少个8KB就分配多少个inode。由于数据块占了整个块组的绝大部分,也可以近似认为数据块有多少个8KB就分配多少个inode,换句话说,如果平均每个文件的大小是8KB,当分区存满的时候inode表会得到比较充分的利用,数据块也不浪费。

6).数据块(DataBlock)

根据不同的文件类型有以下几种情况

对于常规文件,文件的数据存储在数据块中。

对于目录,该目录下的所有文件名和目录名存储在数据块中,注意文件名保存在它所在目录的数据块中,除文件名之外,ls-l命令看到的其它信息都保存在该文件的inode中。注意这个概念:目录也是一种文件,是一种特殊类型的文件。

对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。

设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。

ps:硬盘、U盘、光盘、SD卡等存储设备的数据发生了丢失,使用迷你兔数据恢复软件进行恢复找回,它具有“删除恢复”、“格式化恢复”、“硬盘恢复”、“深度恢复”、“移动存储设备恢复”五大功能模块,恢复效率高,安全性有保障。