Linux ext2文件系统之初步思考
数据存放在磁盘中,磁盘最小存取单位sector(512Byte);文件系统中存储的最小单位是 块(Block),大小通常(1KB,2KB,4KB...),
一个block对应多个sector,因而可用block逻辑上 分割 物理磁盘。
通常文件除了 其内部数据外,还有一些属性需要记录。如 权限,大小等, 即 metadata,
将metadata存放在一个叫 inode 中,而数据data则放在block中,(当然 ,inode本身也是存放在块中),于是一个文件对应了一个inode,现在将inode与block关联起来。
1,索引式,inode存放所有block的索引
2, 链接式 , inode存放首个block,然后每个block指向其下一个
至于目录,与普通文件相同,只是目录的内容是目录项,它应包含 该目录所有文件(含目录)名,及其inode的索引,方便我们能找到对应文件。
此外,为了对Block和inode进行管理,分配。还有个bitmap位图用与标识一个Block有无被使用.
Ext2文件系统
ext2文件系统结构如图:
说明:(此信息从外部复制引用,用背景色标注...以上图片也是拷贝的)
一般来说, superblock 的大小为 1024bytes。相关的 superblock 信息我们可以dumpe2fs 命令来呼叫出来观察!
超级块在每个块组的开头都有一份拷贝。事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock ,
而若含则是第一个 block group 内 superblock 的备份,这样可以进行 superblock 的救援!
二、组描述符表(GDT,Group Descriptor Table):
由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符(Group Descriptor)存储一个块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等。和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝。通常内核只用到第0个块组中的拷贝,当执行e2fsck
检查文件系统一致性时,第0个块组中的超级块和块组描述符表就会拷贝到其它块组,这样当第0个块组的开头意外损坏时就可以用其它拷贝来恢复,从而减少损失。
三、位图 (bitmap) :
其中每个bit表示一个inode/Block是否空闲可用。
测试及思考:
mke2fs时通过 -b 指定blocksize,从而得到 block count.
通常用 -i 来得到 inode count ,其参数 字节/inode,就是每?字节一个inode,通常设为block size 倍数.
(说明: B→block size,Gnum→group count,Bnum→block count,Inum→inode count)
1).因为每个group中用一个B来表示位图,所以一个group中最多8*B个数据块,因而ext2的group分配策略是:每个group大小为8*B (单位:块),
那么 gnum=bnum/8*B,每个组的inode count=inum/gnum,从而得出 inode表占用block的数量
现在需确定 GDT占用 block数,剩下的则都是用于数据块了。而根据dumpe2fs显示结果看,GDT也是固定的,还有 保留的GDT块。这不理解怎么分配的。
另外,只有前两个group有超级块和GDT....
因而每个组中各个数据的偏移位置也就能确定了。从而能根据给定一个 inode idx或 data idx找到其对应group的对应block !!(即找到读写位置)
2).我测试时用dumpe2fs 显示的inode size总是256,而不是128,建的也是ext2,不知道为什么.
而first inode总是11,(刚格式化未建立任何文件).
我能理解的是,为了能正常访问FS中的数据,我需要预先创建一个/根目录,之后的所有新建的文件都在这其下。
也就是标记一个BLOCK作为入口,那么刚格式化时占用一个inode我能理解,为何11个?还需要作什么?
3).inode table中,每个inode size 为128字节,其中 最后60字节用于索引 数据块,15个(12直接,一次,一级,二级……)每个4字节用于指定 block id.
4字节 unsigned 32,可标识 232 =4*G个block,也就是说最多能用于 4*G*B个字节的FS,而ext2有相应的最大系统总容量限制,都没有超过这个。
4)目录在文件系统中具体如何存储?
存储的应是 文件名+inode id,
文件名linux限制最长255,应该是用NUL作结束标志,占256字节。那么inode id用多长来标识?
若定长,则一个块只能放几个目录,测试了下,很明显不是。
所以 ,若不定长,用NUL标识文件名结束,再加一个定长Id,但这样的话,不能……
突然又意识到 ,在磁盘中读取目录内容不正是要读出所有 么。所以递归遍历刚好!!
那么 inode用多长来标识?首先inode count必然小于 block count,所以,还是用4字节标识把,应该...
5). 读取文件系统时,需要先 从入口 /进入,查看其内容,得到子目录列表,然后依次 往下……
直到遍历到所需为止。e.g.如果我要打开文件系统某个文件,我得从根目录开始依次读取下去,直到找到该文件inode,然后再打开。。
这涉及多次读取磁盘,如果目录深度够深,结果 可想....
我之所以会如此思考,是因为,文件系统应独立于OS!
所幸,Linux有其目录系统。从/开始。每个目录或文件,绑定了 inode,先跳转下思路,
当我挂载某个文件系统时,此时,就会遍历该FS整个目录结构,并记录下。续接到其挂载目录之下。
其中包含文件名和inode,因为inode只能用与其本身的文件系统,所以目录树还应包含挂载到目录上的FS,子目录默认继承父目录。
这样我们指定一个path时就能通过目录树,快速找到其所在文件系统,以及inode,从而进行读写.
我想,这也是linux需要 挂载的理由 把------为了生成目录树,(根目录/也有挂载的分区的),方便读写。
顺便一提,ls命令中的文件类型我猜测也是保存于目录树上的。