如果一个文件有多个数据块,这些数据块很可能不是连续存放的,应该如何寻址到每个块呢?
- 根据前面几节的分析,根目录的数据块是通过其 inode 中的索引项 Blocks[0] 找到的,事实上,这样的索引项一共有15个,从 Blocks[0] 到 Blocks[14], 每个索引项占 4 字节。前 12 个索引项都表示块编号,例如上面的例子中 Blocks[0] 字段保存着 24,就表示第 24 个块是该文件的数据块,如果块大小是 1KB ,这样可以表示从 0 字节到 12KB 的文件。如果剩下的三个索引项 Blocks[12] 到 Blocks[14] 也是这么用的,就只能表示最大 15KB 的文件了,这是远远不够的。
- 事实上,剩下的三个索引项都是间接索引。
- 索引项 Blocks[12] 所指向的块并非数据块,而是称为间接寻址块(Indirect Block),其中存放的都是类似 Blocks[0] 这种索引项,再由索引项指向数据块。设块大小是 b ,那么一个间接寻址块中可以存放 b/4 个索引项,指向 b/4 个数据块。所以如果把 Blocks[0] 到 Blocks[12] 都用上,最多可以表示 b/4+12 个数据块,对于块大小是 1K 的情况,最大可表示 268K 的文件。如下图所示,注意文件的数据块编号是从 0 开始的, Blocks[0] 指向第 0 个数据块, Blocks[11] 指向第 11 个数据块, Blocks[12] 所指向的间接寻址块的第一个索引项指向第 12个 数据块,依此类推。
从上图可以看出,索引项 Blocks[13] 指向两级的间接寻址块,最多可表示 (b/4)2+b/4+12 个数据块,对于 1K 的块大小最大可表示 64.26MB 的文件。索引项 Blocks[14] 指向三级的间接寻址块,最多可表示 (b/4)3+(b/4)2+b/4+12 个数据块,对于 1K 的块大小最大可表示 16.06GB 的文件。
可见,这种寻址方式对于访问不超过 12 个数据块的小文件是非常快的,访问文件中的任意数据只需要两次读盘操作,一次读 inode (也就是读索引项)一次读数据块。而访问大文件中的数据则需要最多五次读盘操作: inode、一级间接寻址块、二级间接寻址块、三级间接寻址块、数据块。实际上,磁盘中的 inode 和数据块往往已经被内核缓存了,读大文件的效率也不会太低。