接着上文说高级特性。
Ext2还实现了快速符号链接。符号链接我们前面说过,那什么又叫快速符号链接呢?就是链接没有把它指向的目标名单独用一个数据块来存,而是直接放在inode里面。这样,一能省空间,二是找起来快,少走了一步路嘛。但有好处,就有坏处。它的坏处就在于inode节点的空间是有限的,这个有限的空间就决定了你放在里面的名字不能太长。那么最长是多少呢?60个字符。
Ext2还能记录文件系统的状态。有哪几个状态呢?干净、不干净、错误,一共三个。那么这个状态记录在什么地方呢?在超级块的某处。什么时候记录呢?当Ext2被以读写方式挂载到系统时,记录为“不干净”。当它被卸载或重新以只读方式挂载时,状态被改为“干净”。在引导启动时,文件系统的检查器会去读这个状态,以此来决定是否要对文件系统进行体检。当内核检查到文件系统有不一致时,状态会被写为“错误”。然后文件系统检查器就会强制对文件系统进行检查。
很多时候,用户会跳过检查,大家都很忙,没功夫等你检查完才能进系统干活,还急着干完活交差呢。但总是不检查,据说文件系统又会很危险。那怎么办?就是到了一定条件时,文件系统要进行强制体检。这个条件是什么呢?有两个。1. 在超级块中有一个计数,每次以读写方式加载文件系统时,这个计数就会加1。当这个计数增大到某个指定值时,则必须体检了。2. 在超级块中有上次加载时间和最大检查间隔,一旦发现已经过了最大检查间隔时间,还没有体检,则也必须强制体检了。这些都涉及到了参数,比如最大加载计数,最大检查间隔时间。那这些参数是不是无法更改的呢?答案是No。Ext2提供了一个叫tune2fs的工具,让用户能够更改这些参数:错误行为(就是当发现不一致时,选择是忽略掉继续执行呢,还是重新以只读方式挂载文件系统,以避免损坏文件系统,又或者重启系统,然后用文件系统检查器做个体检)、最大加载计数、最大检查间隔时间、为超级用户保留块数量。另外,在挂载时,有些挂载参数也可以用来改变内核错误行为。
对于大家关注的保密问题,Ext2也是不含糊的。有一个属性,能够让用户对文件进行安全删除。想想不彻底删除的后果吧,比如陈老师的艳照门,就是因为删除照片不彻底,结果被人从硬盘恢复出来,弄的好不尴尬。而如果设置了这个属性呢,当艳照被删除之后呢,文件系统还会将随机的数据写在以前这个文件所在的数据块中。这个就厉害了。因为这样做了之后,艳照就无法恢复了,也就可以大胆地让别人来修电脑了。
它山之石,可以攻玉。Ext2还借鉴了4.4 BSD文件系统的一个想法。就是对于不可更改的文件,它被设置为只读的,就是没人能够写或删除它。这个方法可用来保护比较敏感的配置文件。对于那些只能接着写,而不能覆盖前面内容的文件,可以以写方式打开,但数据只会放在文件末尾。它们也是无法删除或重命名的。哪些文件需要这样做呢?对了,日志文件。
物理结构
Ext2文件系统的物理结构受到BSD文件系统的影响。文件系统由块组(block groups)组成。以前用块组,是希望将连续的东西放在相近的硬盘区域,这样做的好处,就是能够就近访问,减少磁盘寻道时间。于是将硬盘区域分成块组。但由于现在的硬盘驱动已经优化了顺序访问,并且隐藏了实际的物理分布,所以块组现在已经不是物理上的概念了,而只是逻辑上的。
一个文件系统可以用下面的表来表示(来自于原文):
Boot Sector | Block Group 1 | Block Group 2 | ... ... | Block Group N |
Super Block | FS descriptors | Block Bitmap | Inode Bitmap | Inode Table | Data Blocks |
在Ext2中,目录是采用链表的方式来记录目录中的文件项。之前我们说过,目录里面只是放的是目录中文件的inode,那么这个文件项具体包含哪些内容呢?包含的是inode号、该项的长度、名字的长度、文件名。从中我们可以得出:该项的长度是可变的,因为有个值指示它的长度嘛。为什么是可变的呢?因为它不是采用固定长度记录文件名,而是采用变长。因为我们可以看到,还有一个数据项是名字的长度,这样就可以记录各种长度的文件名了。如果采用固定长度文件名,会怎么样呢?要么只能尽可能按照最长的长度来定,这样很多短名字的项就浪费空间了。要么就只能规定一个不大长的文件名长度作为允许的最长文件名,这样就会造成文件的一个缺陷:无法起较长的文件名。目录项的结构如下表所示(来自原文):
inode number | entry length | name length | filename |
原文还以一个包含三个文件:file, long_file_name, f2的目录作为例子,显示了该目录的目录项记录,如下表所示(来自原文):
i1 | 16 | 05 | file1 |
i2 | 40 | 14 | long_file_name |
i3 | 12 | 02 | f2 |