预计阅读本页时间:-
4.4.3 文件系统的一致性
影响文件系统可靠性的另一个问题是文件系统的一致性。很多文件系统读取磁盘块,进行修改后,再写回磁盘。如果在修改过的磁盘块全部写回之前系统崩溃,则文件系统有可能处于不一致状态。如果一些未被写回的块是i节点块、目录块或者是包含有空闲表的块时,这个问题尤为严重。
为了解决文件系统的不一致问题,很多计算机都带有一个实用程序以检验文件系统的一致性。例如,UNIX有fsck,而Windows用scandisk。系统启动时,特别是崩溃之后的重新启动,可以运行该实用程序。下面我们介绍在UNIX中这个fsck实用程序是怎样工作的。scandisk有所不同,因为它工作在另一种文件系统上,不过运用文件系统的内在冗余进行修复的一般原理仍然有效。所有文件系统检验程序可以独立地检验每个文件系统(磁盘分区)的一致性。
一致性检查分为两种:块的一致性检查和文件的一致性检查。在检查块的一致性时,程序构造两张表,每张表中为每个块设立一个计数器,都初始化为0。第一个表中的计数器跟踪该块在文件中的出现次数,第二个表中的计数器跟踪该块在空闲表中的出现次数。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
接着检验程序使用原始设备读取全部的i节点,忽略文件的结构,只返回所有的磁盘块,从0开始。由i节点开始,可以建立相应文件中采用的全部块的块号表。每当读到一个块号时,该块在第一个表中的计数器加1。然后,该程序检查空闲表或位图,查找全部未使用的块。每当在空闲表中找到一个块时,就会使它在第二个表中的相应计数器加1。
如果文件系统一致,则每一块或者在第一个表计数器中为1,或者在第二个表计数器中为1,如图4-27a所示。但是当系统崩溃后,这两张表可能如图4-27b所示,其中,磁盘块2没有出现在任何一张表中,这称为块丢失。尽管块丢失不会造成实际的损害,但它的确浪费了磁盘空间,减少了磁盘容量。块丢失问题的解决很容易:文件系统检验程序把它们加到空闲表中即可。
有可能出现的另一种情况如图4-27c所示。其中,块4在空闲表中出现了2次(只在空闲表是真正意义上的一张表时,才会出现重复,在位图中,不会发生这类情况)。解决方法也很简单:只要重新建立空闲表即可。
最糟的情况是,在两个或多个文件中出现同一个数据块,如图4-27d中的块5。如果其中一个文件被删除,块5会添加到空闲表中,导致一个块同时处于使用和空闲两种状态。若删除这两个文件,那么在空闲表中这个磁盘块会出现两次。

文件系统检验程序可以采取相应的处理方法是,先分配一空闲块,把块5中的内容复制到空闲块中,然后把它插到其中一个文件之中。这样文件的内容未改变(虽然这些内容几乎可以肯定是不对的),但至少保持了文件系统的一致性。这一错误应该报告,由用户检查文件受损情况。
除检查每个磁盘块计数的正确性之外,文件系统检验程序还检查目录系统。此时也要用到一张计数器表,但这时是一个文件(而不是一个块)对应于一个计数器。程序从根目录开始检验,沿着目录树递归下降,检查文件系统中的每个目录。对每个目录中的每个文件,将文件使用计数器加1。要注意,由于存在硬连接,一个文件可能出现在两个或多个目录中。而遇到符号连接是不计数的,不会对目标文件的计数器加1。
在检验程序全部完成后,得到一张由i节点号索引的表,说明每个文件被多少个目录包含。然后,检验程序将这些数字与存储在文件i节点中的连接数目相比较。当文件创建时,这些计数器从1开始,随着每次对文件的一个(硬)连接的产生,对应计数器加1。如果文件系统一致,这两个计数应相等。但是,有可能出现两种错误,即i节点中的连接计数太大或者太小。
如果i节点的连接计数大于目录项个数,这时即使所有的文件都从目录中删除,这个计数仍是非0,i节点不会被删除。该错误并不严重,却因为存在不属于任何目录的文件而浪费了磁盘空间。为改正这一错误,可以把i节点中的连接计数设成正确值。
另一种错误则是潜在的灾难。如果同一个文件连接两个目录项,但其i节点连接计数只为1,如果删除了任何一个目录项,对应i节点连接计数变为0。当i节点计数为0时,文件系统标志该i节点为“未使用”,并释放其全部块。这会导致其中一个目录指向一未使用的i节点,而很有可能其块马上就被分配给其他文件。解决方法同样是把i节点中连接计数设为目录项的实际个数值。
由于效率上的考虑,以上的块检查和目录检查经常被集成到一起(即仅对i节点扫描一遍)。当然也有一些其他检查方法。例如,目录是有明确格式的,包含有i节点数目和ASCII文件名,如果某个目录的i节点编号大于磁盘中i节点的实际数目,说明这个目录被破坏了。
再有,每个i节点都有一个访问权限项。一些访问权限是合法的,但是很怪异,比如0007,它不允许文件所有者及所在用户组的成员进行访问,而其他的用户却可以读、写、执行此文件。在这类情况下,有必要报告系统已经设置了其他用户权限高于文件所有者权限这一情况。拥有1000多个目录项的目录也很可疑。为超级用户所拥有,但放在用户目录下,且设置了SETUID位的文件,可能也有安全问题,因为任何用户执行这类文件都需要超级用户的权限。可以列出一长串特殊的情况,尽管这些情况合法,但报告给用户却是有必要的。
以上讨论了防止因系统崩溃而破坏用户文件的问题,某一些文件系统也防止用户自身的误操作。如果用户想输入
rm *.o
删除全部以.o结尾的文件(编译器生成的目标文件),但不幸键入了
rm *.o
(注意,星号后面有一空格),则rm命令会删除全部当前目录中的文件,然后报告说找不到文件.o。在MS-DOS和一些其他系统中,文件的删除仅仅是在对应目录或i节点上设置某一位,表示文件被删除,并没有把磁盘块返回到空闲表中,直到确实需要时才这样做。所以,如果用户立即发现了操作错误,可以运行特定的一个“撤销删除”(即恢复)实用程序恢复被删除的文件。在Windows中,删除的文件被转移到回收站目录中(一个特别的目录),稍后若需要,可以从那里还原文件。当然,除非文件确实从回收站目录中删除,否则不会释放空间。