文件系统作为一个系统的重要组成部分,对于每位程序员来说,都是非常重要的基础知识。与此同时,Linux和Windows上的文件系统的原理又恰恰是不一样的。Windows中采用的是FAT 表的形式,但是今天我主要的讲的是更为经典的Linux本地文件系统上的存储原理,稍稍分析一下他的结构,作为抛砖引玉。
文件系统的数据块管理
我们都知道,文件要被存储在磁盘中,我们都是把以数据块的概念做处理和存储的,如果最后的剩余部分没有达到单位块的大小,也是作为一整块的方式处理。所以问题来了,我们如何去处理这些文件数据块的关系呢,如何保证查找更加高效。下面提供3种常见的做法:
1.连续分配。这是一种最简单的处理方式,在磁盘中寻找一段空的物理地址,在上面连续划分出足够的物理块,映射到逻辑上的数据块号上去。这样的好处是,如果你知道数据块的首地址,你可以通过计算,随机访问数据块。但是不足之处也很明显,你不知道想存入的数据块的大小,要划分多大的空间。第二,这么做的效率太低了,每次都要刚刚找到这么多的连续的物理空间存储数据块,每次都是成块成块的占去一大片空间,最终会导致很多碎片,因为空间太小,用不了,剩余的那部分小的空间就永远是无法得到利用。
2.链接表法。这个方法相比上个方法就提升了一个档次,首先就是不需要是连续的存储空间的要求。他是通过类似链表的手法在逻辑上保证是数据连续的。通过在文件数据块中多设置了下一个的数据块的物理地址,进行逐个查找访问。下面这张是模拟图;
缺点主要有2个,随机访问效率低,必须要逐个找过去,如果你要找的数据在你最后一个数据块,那就要悲剧了。2.还有一个这会带来额外的存储开销,因为你在文件的基本信息中还保存了物理地址。所以这导致了下一个方式的诞生。
3.索引链表法。这个方法好像就是专门为了克服上个方法的缺点的。不是闲效率低吗,我把索引的地址与真实物理数据分开存放不就可以解决问题了嘛。这其实也就是数据库中的索引的方式。避免了多次的IO操作,直接将索引表放在内存中,一个索引表项中记录了下一个物理块的位置。在内存中逐个查找,总比在磁盘中提供反复的打开文件等这么频繁的IO操作来的效率高。
Linux的文件存储方式
前面说的3个方法就是为了引出下面的正题,在Linux的存储管理中,最接近的方法就是上面3种中的最后一种,在Linux中,人家把所有的文件,目录等都抽象为1个概念,i-node节点,里面存放了文件的元数据和数据结点的索引。下面是张模拟图:
那为什么要有1级索引,2级,3级索引的东西呢,就是为了超大数据块文件设计的,如果你的文件足够小,1,,2个数据块就够了,直接通过i-node上的直接数据块指针就能搞定了。大的话就通过再次索引,这样一展开就可以存储了很多的数据块了。