计算机的内存大小有限,而且属于易失性(就是拔掉电源或者关机,所存储的数据就消失了)的存储介质,所以许多文件是存放在磁盘上,对磁盘的访问属于I/O操作,磁盘的访问速率就对计算机的性能有举足轻重的影响。在此我只浅谈文件的存储分配方式以及访问策略,对硬件的访问速率不做讨论。(磁盘存储的基本单位是块)
1、 连续分配:
连续分配就是在磁盘上分配一组连续的块来存储一个文件,磁盘每个块都有一个地址,且按照线性排列。那么计算机存储文件就只需要存储文件名、文件首地址、文件长度。具体示例如下图:
图1:连续分配
这样的分配方式的优点就在于:1、访问容易;2、由于文件系统会记住上一次访问的地址,所以该方式支持直接访问和顺序访问。
缺点在于:
1)、新文件分配和拓展问题:当文件被创建的时候,我们需要按照文件的大小分配空间,但是在文件的使用过程中,文件可能会变大,也可能会被删除。
如果文件紧贴着彼此,就很难进行拓展;一种解决方式是:当空间不够的时候,在最后一块加一个拓展指针,指向另一空块进行拓展,以此类推。
如果我们给每个文件分配一定的可拓展的空间,但是当用户不再拓展一些文件的时候,就会造成空间的浪费。
2)、外部碎片(整个块没法使用)问题:在不断的增加和删除文件过程中,会造成一些集中的小块(比如图中的18、19块)没法用,它们周围的文件不扩展,也没有这么小的文件可以存储到其中,就会造成浪费。一种解决方案是定期合并这些小的碎片,通过移动其他文件块的位置使这些小碎片集中成一个大块,供以后使用。但是这种方式严重的时间代价,而且会使计算机在此期间无法工作。
2、链接分配:
这种分配方式的思想类似于链表,每个块就是一个节点,每个块的尾部存储下一个块的地址。文件访问时,当访问到一块的最后时,获取下一个块的地址,从而进行下一块的访问,当访问文件结束时,那一块的地址就为一个特定的终止符(图例中的终止符为-1)。那么文件的目录结构就只需要文件名、起始地址、终结地址了。
图2:链接分配
链接分配的优点在于:
1)、不会出现外碎片问题,因为这种分配方式没有位置的限制,任何一个块都可以指向任意块,也可以被任意块指向。
2)、便于拓展:文件如果需要扩展,那么只需要在文件链的尾部添加节点,并且修改原尾节点和文件目录的终结地址即可。
但是链接分配也有它自身的缺陷:
1)、只能顺序访问:由于这种磁盘分配方式采用的链表,所以只能顺序访问,要访问文件的第i块,就必须从头开始,跟着指针,找到第i块。
2)、指针浪费内存:由于每一块都需要存储额外的指针,这样就造成了空间的浪费。一种优化方式是:多块共用一个地址,看成一块,称为簇。这样就可以有效的减少指针的数量,但是如果最后一个簇用不完,例如一个簇包含4个块,但是文件+指针一共需要13个块,那么就需要4个簇,但是最后一个簇就只使用了一个块,而一个簇公用一个地址,所以其他三块就没法分配出去,只能被浪费了。
3、索引分配:
为了解决上面两种方式的问题,可以采用索引分配。索引分配简单的说就是把链接分配的指针集中顺序存放在一个块中,那么文件目录就只需要存储文件名和索引块的地址,然后在这个块中按照地址依次访问,当然也可以通过偏移量直接查询到想访问的地址之后就直接访问。
3、索引分配
这种访问方式有一个问题:就是一个块存储的索引地址的数量是有限的,那么分配该怎么把握呢?针对这一目的的机制包括如下:
1)、链接方案:简单地说,就是用链接分配来拓展索引块,一个索引块用完了,就通过指针链接到下一块。
2)、多层索引:就像树一样,目录的索引块指向根节点,然后块中的地址就指向另一个块,是第二层索引,以此类推。
3)、组合方案:例如在如下的图中,一个索引块含有15个指针(直接块+间接块),其中的头12个指针是直接块;即它们包括了能存储文件数据的块的地址。因此,小文件不需要其他是索引块。一级间接块就是二层索引结构,二级间接块就是三层索引结构,三级间接块就是四层索引结构,通过这种分层的方式,可以使大小不同文件分配到合适的索引结构。
图4、组合分配方案