根文件系统在linux下非常重要,基本上跟所有的模块都有紧密的联系,linux用文件形式对用户程序提供了统一的视角去看待,包括字符设备,块设备,网络等都抽象成文件使用统一的api来调用
为什么需要根文件系统呢?
设想,如果我们是内核开发人员,是直接跟外存打交道的,通过给端口发指令告诉驱动程序去读取某个盘某个扇区,如果我们要存储一些二进制内容,我们就必须把存储的起始位置和结束位置记录下来,下次读取的时候用记录的位置读取出来就能实现“存取”了。
于是,很自然的我们就可以想到我们需要一种方式就标记存储这些分散在不同的地方的信息,于是我们就把不同的信息抽象成文件,很符合我们生活中的常识,文件是个对象,有名字,大小,创建时间,还有最重要的标记在外存设备中对应的存储未知的信息。
现在我们有了文件,我们就需要一种把他们组织起来的办法了,就像我们去图书馆,我们先要规定一种图书的摆放的规则(比如根据类别分类摆放),然后我们把书柜贴上对应的类目,工作人员根据类目摆放对应的图书,一旦第一次创建完成后,以后不管是同学来借书还是还书,亦或来了新书,工作人员都可以根据目录很快的完成工作。
MINIX根文件系统
最早的linux是在minix系统上交叉编译的,为了方便直接使用了minix的根文件系统,根据上面图书馆的例子,我们确定我们需要抽象3个概念
- 汇总信息(包含所有目录的存档,书本数量等)
- 类目录明细(记录目录名称,目录下书籍索引)
- 书本信息(书名称,作者,出版日期,存放准确位置)
现在回到文件系统,minix也规定了3类,拿软盘举例,minix系统按1KB为单位拆分,第一块默认不用,第二块是超级快,对应上面的汇总信息。紧接着是i节点位图,对应我们的类目录,再跟着是i节点,对应我们的书本信息,再往后是真正的数据块,这才是真正存储文件信息的地方。
这样一来,我们就可以在我们的外存设备中有规则的组织数据了。
顺便提一下,我们在windows里肯定知道给硬盘分区,其实就是给硬盘分出了几块,然后给对应的块初始化成对应的文件系统,这也就可以解释为什么一个文件如果我们只是在一个盘内移动,基本上是瞬间完成的。而比如从C盘拷一个文件到D盘可能花很长时间,这就是因为跨文件系统了,文件系统内移动其实只是改动一个指针,而跨文件系统就要真正的复制了。我们也可以用图书馆例子举个不很严谨的例子,我们可以假设同盘内移动,我们只需要在原目录中删去该书的索引信息,然后在新的目录中增加该书的索引信息。而夸盘移动,我们就真的需要拿着这本书去对方的图书馆了。
image.png超级快--汇总信息
超级快记录了总i节点数,逻辑块数,以及记录他们存在的对应的位图数,操作系统也就是根据超级快来处理该分区的文件操作的。
image.png
i节点
根据位图我们知道哪些节点被占用了,对应i节点占用32个字节长度,i节点可以是一个文件夹也可以是一个文件,由i_mode标识,采用最多2级目录方式,这样当小文件时一次寻址,大文件通过多级目录寻址来平衡两者。
image.png
结合例子
我们把根目录软盘用hexdump查看一下
hexdump /dev/fd1 | more
image.png
- 0x0000-0x03ff 是第一个块,默认是不用的
- 0x0400-0x07ff 是超级块,先来分析它
首先我们根据上面超级快的定义来确定字段内容
1. s_ninodes i节点数 0x01e0=480 实际占用块数=480*32/1024=15
2. s_nzones 逻辑块数 0x05a0=1440
3. s_imap_blocks i节点位图块数 0x0001=1
4. s_zmap_blocks 逻辑快位图数 0x0001=1
5. s_firstdatazone 数据区第一块逻辑块号 0x0013=19
6. s_log_zone_size 磁盘快/逻辑块=0
7. s_max_size 最大文件长度 0x10081c00=268966912
8. s_magic 文件系统幻数 0x137f
- 0x0800-0x0bff 是i节点位图
- 0x0c00-0x0fff 是逻辑块位图
- 关键的i节点到了,我们已经知道了i节点一共占用15个块,那么就是0x1000-0x4bff是存放i节点
#因为占用32个字节,我们先看第一个节点(根目录)
i_mode 0x41ed drwxr-xr-x
i_uid 0x0000
i_size 0x00000080 128字节
i_mtime 0x842eaa9e
i_gid 0x0800
i_nlinks 0x0013 zone[0]=0x0013其他是0
#那我们现在去看0x0013数据块,首先我们已知目录大小128字节
#又前面知道每个目录项16字节,所以根目录下一共有128/16=8个目标,数据块从0x13开始,那么就是0x4c00开始
// 文件目录项结构。
struct dir_entry
{
unsigned short inode; // i 节点。2字节
char name[NAME_LEN]; // 文件名。 14字节 ascii字符
};
前两行都是指向0001节点,名字分别是"."和"..",只有根目录的..也指向自己
第三行 0002节点 bin
第四行 0006节点 dev
第五行 0019节点 etc
第六行 001e节点 usr
第七行 003c节点 tmp
第八行 0044节点 root
image.png
网友评论