好文分享:EXT文件系统机制原理详解(8)
第14个指针i_block[13]是二级间接寻址指针,它指向一个仍然存储了指针的block,但是这个block中的指针还继续指向其他存储指针的block,即i_block[13] --> Pointerblock1 --> PointerBlock2 --> datablock。 第15个指针i_block[14]是三级间接寻址指针,它指向一个任然存储了指针的block,这个指针block下还有两次指针指向。即i_block[13] --> Pointerblock1 --> PointerBlock2 --> PointerBlock3 --> datablock。 其中由于每个指针大小为4字节,所以每个指针block能存放的指针数量为BlockSize/4byte。例如blocksize为4KB,那么一个Block可以存放4096/4=1024个指针。 如下图。 为什么要分间接和直接指针呢?如果一个inode中15个指针全是直接指针,假如每个block的大小为1KB,那么15个指针只能指向15个block即15KB的大小,由于每个文件对应一个inode号,所以就限制了每个文件最大为15*1=15KB,这显然是不合理的。 如果存储大于15KB的文件而又不太大的时候,就占用一级间接指针i_block[12],这时可以存放指针数量为1024/4+12=268,所以能存放268KB的文件。 如果存储大于268K 的文件而又不太大的时候,就继续占用二级指针i_block[13],这时可以存放指针数量为[1024/4]^2+1024/4+12=65804,所以能存放65804KB=64M左右的文件。 如果存放的文件大于64M,那么就继续使用三级间接指针i_block[14],存放的指针数量为[1024/4]^3+[1024/4]^2+[1024/4]+12=16843020个指针,所以能存放16843020KB=16GB左右的文件。 如果blocksize=4KB呢?那么最大能存放的文件大小为([4096/4]^3+[4096/4]^2+[4096/4]+12)*4/1024/1024/1024=4T左右。 当然这样计算出来的不一定就是最大能存放的文件大小,它还受到另一个条件的限制。这里的计算只是表明一个大文件是如何寻址和分配的。 其实看到这里的计算数值,就知道ext2和ext3对超大文件的存取效率是低下的,它要核对太多的指针,特别是4KB大小的blocksize时。而ext4针对这一点就进行了优化,ext4使用extent的管理方式取代ext2和ext3的块映射,大大提高了效率也降低了碎片。 6 单文件系统中文件操作的原理在Linux上执行删除、复制、重命名、移动等操作时,它们是怎么进行的呢?还有访问文件时是如何找到它的呢?其实只要理解了前文中介绍的几个术语以及它们的作用就很容易知道文件操作的原理了。 注:在这一小节所解释的都是在单个文件系统下的行为,在多个文件系统中如何请看下一个小节:多文件系统关联。 6.1 读取文件当执行"cat /var/log/messages"命令在系统内部进行了什么样的步骤呢?该命令能被成功执行涉及了cat命令的寻找、权限判断以及messages文件的寻找和权限判断等等复杂的过程。这里只解释和本节内容相关的如何寻找到被cat的/var/log/messages文件。
因为GDT总是和superblock在同一个块组,而superblock总是在分区的第1024-2047个字节,所以很容易就知道第一个GDT所在的块组以及GDT在这个块组中占用了哪些block。 其实GDT早已经在内存中了,在系统开机的时候会挂载根文件系统,挂载的时候就已经将所有的GDT放进内存中。
前文说过,ext文件系统预留了一些inode号,其中"/"的inode号为2,所以可以根据inode号直接定位根目录文件的data block。
通过var目录的inode指针,可以寻找到var目录的inode记录,但是指针定位的过程中,还需要知道该inode记录所在的块组以及所在的inode table,所以需要读取GDT,同样,GDT已经缓存到了内存中。
将上述步骤中GDT部分的步骤简化后比较容易理解。如下:找到GDT-->找到"/"的inode-->找到/的数据块读取var的inode-->找到var的数据块读取log的inode-->找到log的数据块读取messages的inode-->找到messages的数据块并读取它们。 6.2 删除、重命名和移动文件 注意这里是不跨越文件系统的操作行为。
对于删除普通文件: (1)找到文件的inode和data block(根据前一个小节中的方法寻找); (2)将inode table中该inode记录中的data block指针删除; (3)在imap中将该文件的inode号标记为未使用; (4)在其所在目录的data block中将该文件名所在的记录行删除,删除了记录就丢失了指向inode的指针; (5)将bmap中data block对应的block号标记为未使用。 对于删除目录文件:找到目录和目录下所有文件、子目录、子文件的inode和data block;在imap中将这些inode号标记为未使用;将bmap中将这些文件占用的 block号标记为未使用;在该目录的父目录的data block中将该目录名所在的记录行删除。需要注意的是,删除父目录data block中的记录是最后一步,如果该步骤提前,将报目录非空的错误,因为在该目录中还有文件占用。 关于上面的(2)-(5):当(2)中删除data block指针后,将无法再找到这个文件的数据;当(3)标记inode号未使用,表示该inode号可以被后续的文件重用;当(4)删除目录data block中关于该文件的记录,真正的删除文件,外界再也定位也无法看到这个文件了;当(5)标记data block为未使用后,表示开始释放空间,这些data block可以被其他文件重用。 (编辑:ASP站长网) |