,虽然ext2文件系统支持大于2GB的单一文件,但是有的程序依然使用旧的限制,也就是说只能够捉到小于2GB以下的文件
1>.原则上block的大小与数量在格式化后就不能够再改变(除非重新格式化)
2>.每个block内最多只能放置一个文件的数据
3>.如果一个文件大于block的大小,则会占用多个block
4>.若文件小于block,则该block的剩余容量就不再能被使用。(磁盘空间会浪费)
- inode table:inode的内容在记录文件属性以及该文件实际数据是在哪几号block内,inode记录的文件数据至少如下:
1>.该文件的存取模式(read/write/ excute)
2>.该文件的拥有者与群组(owner/group)
3>.该文件的容量。
4>.该文件最近一次状态改变的时间(ctime)
5>.该文件最近一次的读取时间(atime)
6>.该文件最近一次修改时间(mtime)
7>.定义文件的特性(flag),如setUID
8>.该文件真正的指向(pointer)
此外inode的数量和大小也是在格式化时就已固定,inode还有一些特色:
1>.每个inode大小为128bytes
2>.每个文件仅会占用一个inode而已
3>.因此文件系统能够建立的文件数量和inode的数量有关
4>.系统读取文件的时候首先找到inode,并分析inode所记录的文件权限与用户是否符合,若符合才能够开始实际读取block的内容
inode/block与 文件大小的关系:inode要记录的数据非常多,但偏偏只有128bytes,而inode记录一个block号码要花掉4bytes,假设我的一个文件有400MB且每个block只有4K,那么至少要十万笔block的号码的记录,inode哪有这么多可记录的信息?为此我们的系统很聪明的将inode记录的block号码区域定义为12个直接、一个间接,一个双间接与一个三间接记录区。inode的结构如下。
最右边的inode本身(128bytes),里面有12个直接指向block号码
,这12笔记录就能够直接取得block号码。至于间接就是再拿一个block来当做记录block号码的记录区,如果文件太大时就会使用间接block来记录编号。上图只是拿一个block来记录额外的号码。同理,如果文件持续长大,那么就会利用双间接,第一个block仅再指出下一个记录编号的block在哪里,实际记录在第二个block中,以此类推这样的inode能指定多少个block呢,我们以1k block 来说明:
1>.12个直接指向:12*1k=12K。由于直接指向所以总共记录12笔,总额大小就是12k
2>.间接:256*1k=256k。每笔block号码会花去4bytes,因此1k大小的能够记录256笔记录,一个间接可以记录的文件大小就是256k。
3>.双间接:256*256*1k=
(用的笔记软件不支持...)。第一层block会指定256个第二层,每个二层可以指定256个号码。
4>.三间接:256*256*256*1k=
。第一层block会指定256个第二层,每个第二层可以指定256个第三层,每个第三层又可以指定256
个号码。
总额:将直接、间接、双间接、三间接加总,得出12+256+256*256+256*256*256(k)=16GB
因此我们知道当block为1k的时候,能够容纳的最大文件为16GB,比较文件限制表的结果是一致的。但这个方法不能用在2k、4kblock大小的计算中,因为2kblock会受到ext2文件系统的限制,所以计算的结果可能不符合
2>.未使用与已使用inode/block数量
3>.block与inode大小(block为1,、2、4k,inode为128bytes)
4>.filesystem的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息
5>.一个valid bit数值,若此文件系统已挂载,则valid bit 为0,若未被挂载valid bit为1
supperblock是非常重要的,因为我们这个文件系统的基本信息都写在这里,因此,如果supperblock死掉了,你的文件系统可能需要花很多的时间去挽救。
一般来说supperblock大小为1024bytes。此外,block group 都可能含有supperblock,但是我们也说一个文件系统应该仅有一个supperblock,事实上第一个group block内会含有supperblock之外,后续的block group不一定含有supperblock。而若含有superblock则该supperblock主要是作为第一个block group内supperblock的备份,这样可以进行supperblock的救援。
- filesystem description(文件系统描述说明):这个区段可以描述block group的开始与结束的block号码。以及每个区段分别介于哪一个block号码之间,这部分能用dumpe2fs来观察
- block bitmap(区块对照表):新增文件的时候总会用到block,那会使用那个block来记录呢?当然是选择空的block记录新文件的数据,那怎么才能知道block为空呢?这就要透过block bitmap的辅助了。 从block bitmap当中可以知道哪些block是空的,因此我们的系统就能够很快速的找到可使用的空间来处置文件。同样的,如果你删除了某些文件时,那么那些文件原本占用的block号码就需要释放出来,此时block bitmap当中相对应到该block号码标志就需要修改成未使用中。block bitmap的功能就是如此
- inode bitmap(inode对照表):inode bitmap与block bitmap是类似的功能,只是inode bitmap记录的是inode的未使用和使用
ext2文件系统中目录与文件的关系(实际上需要遵循Unix的思想,一切都是文件,这样理解起来更好些。):
1.目录:我们知道Linux ext2文件系统在建立一个目录时,ext2会分配一个inode与至少一块block给该目录。其中,inode记录该目录相关的权限、属性等,并可记录分配到的那块block号码。而block则是记录在这个目录下的文件名与该文件名占用的inode号码数据
这就是目录分配到的block记录的数据
2.文件:当我们在Linux下的ext2建立一个一般文件时,ext2会分配一个inode与相对于该文件大小的block数量给该文件,例如:假设我的block为4k,而我要建立一个100bytes的文件时,那么Linux将分配一个inode和25个block来存储该文件。而我们的inode有12个直接指向能够指向:12*4k=48k,剩下的52k就会使用一个block来使用间接,间接数量仅会被占用的数量为:52k*1024/4bytes = 14个。
3.目录树的读取:inode本身是不会记录文件名的,文件名是保存在文件数据所在的block中。因为文件名是存在block中的,那么我们读取一个文件时,务必会经过目录的inode和block,然后才能够找到那个待读取文件的inode号码,最终才会读到正确的文件的block数据。由于目录树是从根目录(/)开始的,因此系统透过挂载的信息可以找到挂载点的inode号码(通常一个filesystem的最顶层inode号码是由2开始的),此时就能读到根目录的inode内容,并根据inode读取根目录的block内的文件名数据,再一层一层的往下读到正确的文件名。比如,我要找/etc/passwd这个文件时
,该文件的读取流程为:
1>. /的inode:透过挂载点的信息找到/dev/sda2的inode号码为2的根目录inode,且inode规范的权限
让我们可以读取该block的内容(我这里是root所有者,有r和wx权限)
2>. /的block:经过上面的步骤取得block的号码,并找到内容有etc/目录的inode号码(1944961)
3>. etc/的inode:读取1944961号inode得知root具有rx权限,因此可以读取etc /的block内容
4>.etc/的block:经过上个步骤取得inode号码,并找到该内容有passwd文件的inode号码(1947415)
5>.passwd的inode:读取1947415号inode得知root具有rw权限,因此可以读取passwd的block内容
重点是r权限
6>.passwd的block:最后将block内容的数据读出来。
ps:也就是/是一个目录,需要在挂载的sda2找inode2,也就是根目录的inode号,找到inode后会检验权限。如果具有r和x权限,那么就来到inode中用来保存文件inode number和文件名的block,找到etc的inode,进入etc的inode,验证权限,然后读取inode中的block内容。再读取passwd的inode,检验权限,然后进入实际存放内容的block区块,读出数据
filesystem大小与磁盘读取效能 :关于文件系统的使用效率上,假如你的一个文件系统规划的很大时,由于硬盘上的数据总是来来去去。所以,整个文件系统上面的文件通常无法连续写在一起(block号码不连续),而是填入式的将数据填入没有使用的block当中。如果文件写入的block真的很分散,此时就会有文件数据离散的问题发生。虽然ext2的inode已经将文件所记录的block号码都记上,资料可以一次性读取,但如果文件真的太过于离散,确实还是会发生效率低下的问题,因此磁盘取头还是要在整个文件系统中来来去去的频繁读取。如果真的这样,那么可以将整个filesystem内的数据全部复制出来,将该filesystem重新格式化,再将数据给它复制回去就行了。此外,filesystem如果真的太大了,那么当一个文件分别记录在这个文件系统中最前面和最后面的block号码中,此时会造成硬盘的机械手臂移动幅度大,也会造成读取效能的低落。而且读取头再搜寻整个filesystem时,也会花费比较多的时间搜寻~因此,每个分割槽(partition)的规划并不是越大越好,而是针对你的主机用途来进行规划。
ext2/ext3文件的存取与日志式文件系统的功能:
新建一个目录或文件时ext2处理方式:
1.先确定用户对欲新增文件的目录是否具有w与x的权限,若有的话才能新增。
2.根据inode bitmap找到没有使用的inode号码,并将新文件的权限/属性写入
3.根据block bitmap找到没有使用的block号码,并将实际的数据写入block中,且跟新inode和block的指向数据
4.将刚刚写入的inode与block数据同步更新inode bitmap与block bitmap,并更新superblock的内容
一般来说,我们将inode table与data block称为数据存放区域,至于其他例如supperblock和、block bitmap、inode bitmap等区段就被称为 metadata(中介数据)。
因为supperblock、inode bitmap和block bitmap的是数据经常变动,每次新增移除,编辑时都可能影响到这三部分的数据,因此才被称为中介数据
数据不一致:
在一般情况下,新增动作可以顺利完成,但是如果你的文件写入系统时断电或者核心发生错误等,因为不知名的原因导致系统中断。所以写入的数据仅有inode table和data block而已,最后一个同步更新中介数据的步骤并没有做完,此时就会发生metadata的内容与实际数据存放区块不一致的情况。在早期的ext2文件系统中,如果发生这个问题,那么系统在重新启动的时候,就会藉由superblock中的 valid bit(是否有挂载)与filesystem state(clean与否)等状态来判断是否强制进行是数据一致性的检查,若有需要则以e2fsck这支程序来进行。
日志式文件系统( journaling filesystem):
因为数据不一致的检查要针对metadata与实际数据存放区进行对比,这是很慢的。。为了避免文件系统不一致的情况,因此有人想出一个方式,如果我们在filesystem中规划一个区块,该区块专门记录写入与修订文件时的步骤那就能简化一致性检查的步骤了,步骤如下:
1.预备:当系统要写入一个文件时,会先在日志记录区块中记录某个文件准备要写入的信息。
2.实际写入:开始写入文件的权限与数据,开始更新metadata的数据
3.结束:完成数据与metadata的更新后,在日志记录区块当中完成该文件的记录
在这样的程序当中,万一数据记录当中出现了问题,那么我们的系统只需要去检查日志记录区块,就可以知道那个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块filesystem去检查。