下面是mkfs命令的一个例子
mkfs /dev/hd6 60000
结果:
20000个inodes,60000个blocks,第一个数据块块号为638
指导思想:
不看源代码的话,格式化一个文件系统,应该改变的是:
(1),文件系统的超级块信息,需要用户输入的块的总数算出i节点的个数和i节点位图块的个数和逻辑块位图块的个数及第一个数据块的块号。setup_tables()函数完成这个任务。
(2),建立根目录,需要申请一个数据块,需要申请一个根目录对应的i节点,是文件系统中的第一个节点。
修改根目录对应的i节点在i节点位图中对应的位和根目录所在的块对应的逻辑块位图中的位。
make_root_inode();函数完成这个任务。
(3)源程序里还有第三个任务,就是统计磁盘分区中坏块的数目,并把所有的坏块看成一个坏块文件,这个坏块文件对应第二个节点。make_bad_inode()函数完成这个任务。
思路分析:
main()函数首先取得用户给出的块数放到BLOCKS里。
然后调用setup_tables()函数,setup_tables()函数的作用是根据块数算出i节点的总数既块数的三分之一。
然后算出i节点位图的块数和逻辑块位图的块数,还有第一个数据块的块号。
然后把逻辑块位图块清零(范围是数据区对应的位图既FIRSTZONE之后的块对应的位)和把i节点位图块清零(第一个位没有清零,第一个位对应根节点)。然后初始化了i节点缓冲区。最后打印出超级块信息。
区块的数目ZONES既块数BLOCKS为60000,INODES的数目为块数的三分之一既20000。
i节点位图的块数IMAPS为3。
#define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
NORM_FIRSTZONE数目既数据区前面的块数。
ZMAPS = 0;
while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK))
ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK);
逻辑块位图的块数ZMAPS为8。
FIRSTZONE = NORM_FIRSTZONE;
这时FIRSTZONE为2+3+8+(20000/32)=2+3+8+625=638
所以第一个数据块的块号FIRSTZONE为638。
{
int i;
memset(inode_map,0xff,sizeof(inode_map));
memset(zone_map,0xff,sizeof(zone_map));
memset(super_block_buffer,0,BLOCK_SIZE);
MAGIC = SUPER_MAGIC;
ZONESIZE = 0;
MAXSIZE = (7+512+512*512)*1024;
ZONES = BLOCKS; /*BLOCKS为60000 */
/* some magic nrs: 1 inode / 3 blocks */
INODES = BLOCKS/3; /* INODES为20000 */
/* I don't want some off-by-one errors, so this hack... */
if ((INODES & 8191) > 8188)
INODES -= 5;
if ((INODES & 8191) < 10)
INODES -= 20;
IMAPS = UPPER(INODES,BITS_PER_BLOCK);
ZMAPS = 0;
while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK))
ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK);
FIRSTZONE = NORM_FIRSTZONE;
for (i = FIRSTZONE ; i<ZONES ; i++)
unmark_zone(i);
for (i = ROOT_INO ; i<INODES ; i++)
unmark_inode(i);
inode_buffer = malloc(INODE_BUFFER_SIZE);
if (!inode_buffer)
die("Unable to allocate buffer for inodes");
memset(inode_buffer,0,INODE_BUFFER_SIZE);
printf("%d inodes\n",INODES);
printf("%d blocks\n",ZONES);
printf("Firstdatazone=%d (%d)\n",FIRSTZONE,NORM_FIRSTZONE);
printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE);
printf("Maxsize=%d\n\n",MAXSIZE);
}
问题1:为什么setup_tables()函数开始要把zone_map[]数组都置位?
static char zone_map[BLOCK_SIZE * Z_MAP_SLOTS];
memset(zone_map,0xff,sizeof(zone_map));
因为开始不知道FIRSTZONE的大小,需要计算,计算完了之后再清零。
unmark_zone(i);
意思是数据区前面的块都已经使用了。
当然也可以不用先置位再清零。算出FIRSTZONE之后直接把数据区之前的应用mark_zone()函数也可;
问题2:为什么i节点的总数和块的总数是1:3的关系,这个也可以是1:4。