在前面一节中介绍了文件系统的基本概念,接下来就要准备开始实现我们的文件系统,下面是为管理文件系统提供的几个基础数据结构。
超级块的结构1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/* 超级块 */
struct super_block
{
uint32_t magic; // 用来标识文件系统类型,支持多文件系统的操作系统通过此标志来识别文件系统类型
uint32_t sec_cnt; // 本分区总共的扇区数
uint32_t inode_cnt; // 本分区中inode数量
uint32_t part_lba_base; // 本分区的起始lba地址
uint32_t block_bitmap_lba; // 块位图本身起始扇区地址
uint32_t block_bitmap_sects; // 扇区位图本身占用的扇区数量
uint32_t inode_bitmap_lba; // inode位图起始扇区lba地址
uint32_t inode_bitmap_sects; // inode位图占用的扇区数量
uint32_t inode_table_lba; // inode表起始扇区lba地址
uint32_t inode_table_sects; // inode表占用的扇区数量
uint32_t data_start_lba; // 数据区开始的第一个扇区号
uint32_t root_inode_no; // 根目录所在的I结点号
uint32_t dir_entry_size; // 目录项大小
uint8_t pad[460]; // 加上460字节,凑够512字节1扇区大小
} __attribute__((packed));
inode的结构
1 | struct inode |
目录和目录项的结构
1 | enum file_types |
有了这些结构之后,第一步要做的工作就是对硬盘上的分区进行格式化
创建的步骤如下
- 根据分区大小,计算分区文件系统各元信息需要的扇区数及位置
- 在内存中创建超级块,将上面的元信息写入超级块
- 将超级块写入磁盘
- 将元信息写入磁盘上各自的位置
- 将根目录写入磁盘
1 | static void partition_format(struct partition *part) |
这个函数的主要功能实际上就是按照我们对文件系统的规划,将硬盘每一个分区中的信息进行了初始化。这些数据就是用来记录硬盘分区的基本信息,将下图中的信息确定并保留下来。
1 | /* 在磁盘上搜索文件系统,若没有则格式化分区创建文件系统 */ |
在成功创建出文件系统之后,输入了该文件系统中四个主分区的起始扇区地址和该分区的扇区总数。
有了文件系统之后,我们就能对磁盘上的数据进行有效的管理,接下来就要实现文件的创建与删除操作。