linux内核研究笔记7(minix文件系统总结)
《linux内核完全注释》第12章对minix文件系统已经作了比较详细的说明。本文做些简单的总结并且做些实践的记录。
以12章360k的存储磁盘为例,如下图:
该图基本上还是包含了minix文件系统的各个成分,但是有些东西说得还是不够。
1.一个文件系统,在格式化构建文件系统的时候,很多信息都已经被确定下来了,比如i节点位图所占存储块数量,逻辑块位图所占存储块数量,i节点所占空间等等。
2.上图有些地方容易让人误导,以为i节点位图和逻辑块位图就仅占一个块,i节点占4个块。这是不对的,这个数量在初始化文件系统的时候决定下来,不同大小的存储介质,这些东西都是不一样的。上图应该弄些说明可能更准确些。
3.超级块用来指定整个文件系统的信息。比如索引节点数量,第一个数据块起始编号等等。
4.i节点简单理解就是具体的单个文件信息。目录也是一个文件,无非目录的数据区存储的是目录项,目录项包含i节点编号和文件名字符串。
下面以具体的例子来说明一个minix文件系统的细节:
1.首先我们在ubuntu系统里面构建一个minix文件系统的镜像。
[email protected]:~/work/temp/filesystem$ dd if=/dev/zero of=minix.img bs=1k count=360
记录了360+0 的读入
记录了360+0 的写出
368640 bytes (369 kB, 360 KiB) copied, 0.00172698 s, 213 MB/s
[email protected]:~/work/temp/filesystem$ mkfs.minix minix.img
128 inodes
360 blocks
Firstdatazone=8 (8)
Zonesize=1024
Maxsize=268966912
我们构建了一个minix.img镜像文件,这个镜像文件格式化成minix文件系统。大小为360k,从输出信息可以知道,有些数据在格式化之后,就确定下来,比如:
(1)总共128个i节点
(2)总共360个块
(3)第一个数据区编号为8
(4)zone的大小是1024字节
(5)文件最大尺寸是268966912
为啥第一个数据区从8开始?第一个引导块,第二个是超级块,可见3~7的5个区块留给位图区和i节点区。至于这些分别占用多少区块,需要从超级块的数据里面获得,现在还不知道。
2.挂载这个镜像文件,然后人为生成一些文件和目录。
[email protected]:~/work/temp/filesystem$ mkdir mnt
[email protected]:~/work/temp/filesystem$ sudo mount minix.img -o loop mnt
[email protected]:~/work/temp/filesystem/mnt$ tree
.
├── bbb.txt
└── mydir
└── aaa.txt
1 directory, 2 files
[email protected]:~/work/temp/filesystem/mnt$ cat bbb.txt
bbb
[email protected]:~/work/temp/filesystem/mnt$ cat mydir/aaa.txt
aaa
[email protected]:~/work/temp/filesystem/mnt$ sync
3.查看minix.img镜像里面的数据。输出如下:
4.对比引导块。我们发现这1k数据都是0。我们没有使用引导块,保留。
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
5.对比超级块。
00000400 80 00 68 01 01 00 01 00 08 00 00 00 00 1c 08 10 |..h.............|
00000410 8f 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
对应超级块的结构体和字段数据如下:
struct d_super_block {
unsigned short s_ninodes; //0x0080,十进制128,inode总共128个
unsigned short s_nzones; //0x0168,十进制360,总共360个zone
unsigned short s_imap_blocks; //0x0001,十进制1,inode位图占1个块
unsigned short s_zmap_blocks; //0x0001,十进制1,zone位图占1个块
unsigned short s_firstdatazone;//0x0008,十进制8,第一个数据区编号是8
unsigned short s_log_zone_size;//0x0000,log表示的一块数据大小,1kb
unsigned long s_max_size; //0x10081c00,十进制268966912,最大文件长度
unsigned short s_magic; //0x138f,minix魔数
};
以上才多少字节,肯定不能完全占用1k啊,但是规定就是这样,就算不能占用所有1k空间,也给你留着,以备不时之需。可以看到,没有用到数据区全部为0。
6.对比i节点位图。
一个比特位0/1表示一个i节点是否被使用。
00000800 1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000810 fe ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000820 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
我们看到前面16个字节,第一个字节是0x1f=0b00011111,后面15个字节都是0。16个字节刚好等于128位,由超级块可知,总共有128个i节点。第一个位图不用,但是置为1,这样一算,是不是少了一位了,只有127位。我们看到后面有一个0xfe,这里还有一位是0,加上之前16字节里面的127位,刚好是128个位。
7.对比数据区块位图。
00000c00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000c20 00 00 00 00 00 00 00 00 00 00 00 00 fe ff ff ff |................|
00000c30 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
以上从0x1f到0xfe,出去第一位不用,刚好352个位图。这个应该是数据区块的位图占用记录,而第一个数据区从8开始。
8.对比i节点数据。
minix使用32字节的结构表示一个i节点的数据,其结构体如下:
struct m_inode {
unsigned short i_mode; //0x41ed,040755, 目录文件, rwxr-xr-x
unsigned short i_uid; //0x03e8, 1000
unsigned long i_size; //0x00000080, 128
unsigned long i_mtime; //0x5cb93ad2
unsigned char i_gid; //0xe8
unsigned char i_nlinks; //0x03
unsigned short i_zone[9]; //0x08,i_zone[0]=8,数据块在第8号区块
};
9.对比数据区。
第一块数据区,实际上是根目录的数据区,根目录的数据区里面存放的是目录项,每个目录项,minix2.0是32位,minix1.0是16位。一个目录项表示一个目录或者文件,其中2字节表示这个目录或者文件的inode节点序号,剩下的字节用于存放文件名字符串。其中第一个目录项表示'.',第二个表示'..'。如下:
00002000 01 00 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
前面两个字节0x0001,表示节点序号为1,后面0x2e是'.'字符的ascii码。依次类推,就不一一举例了。
如果是普通文件的数据区,则直接存放文件内容,具体在什么数据区由i节点数据表示。