yjn1187 / LinuxFileSim

基于Linux的Ext2文件系统模拟

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

基于Linux的Ext2文件系统模拟

特点

  • 与用户交互,在内存中开辟空间来模拟文件系统的运行

  • 实现了touchrmlsmkdircd等Linux文件操作命令

  • 基于Linux的inode(索引节点)与位图技术

程序主要功能

1、在内存中开辟一块空间来模拟文件系统的运行,不读写硬盘。

2、面向单用户、单任务,不考虑并发,不考虑文件属主、组等概念。

3、程序开始后,初始化并接收用户输入。若输入”enter”,则重新建立文件系统, 读取上次的退出状态,以上次目录为当前目录; 若输入”q”则退出程序。

系统采用命令行方式与用户交互:touch, rm, ls, mkdir, rmdir, cd ;显示每条命令的执行结果;然后准备接收下一条命令。

用户输入”exit”后,保存当前状态,退出系统 ,等待用户输入。

主要数据结构

1、文件的属性:

​ 文件名(最大长度?) ;

​ 文件类型:目录、数据;不考虑链接。

​ 文件权限:w/r/x ;

​ 文件大小:字节为单位。

​ 文件最后修改时间:取程序运行来的时钟滴答数(转换为float)。

2、文件系统的组织:模仿ext2文件系统。

​ 超级块:结构体;

​ 组描述:结构体;

​ 块位图:一维数组;

​ inode位图:一维数组;

​ inode table::二维数组,每行am位表示**,nx位表示**… ;

​ 数据块:每个数据块的头2个字节作指针,指向同一文件的下一数据块。

3、文件的结构:

​ 数据文件:第一个数据块的地址在inode table 表项中,后续数据块通过指针连接起来;

​ 目录文件:同上。每2个字节用来记录一个子inode。

​ 存储空间组织:内存空间分成若干小块。

4、关于touch

touch filename:若filename不存在,则创建新数据文件,分配inode,不分配数据块;若filename存在,则修改文件时间。

touch size filename: 若filename不存在,则创建新数据文件,分配inode,根据size分配数据块; 若filename存在,则修改文件大小和时间。

5、其他命令均简单实现:

rm删除一个文件,cd 改变工作目录,mkdir创建一个目录文件,rmdir删除一个空目录。所有命令都要有输出(结果或信息)。

主要算法

在Ext2文件系统中的所有块组大小相同并被顺序存放。在本实验中,并没有设计完整分区,只设计了分区中的一个块组,大小128MB,组描述符也只占一个块。设计块大小为4KB,每个4KB的块位图描述32K个数据块,组成块组的总体大小128MB。

文件系统中的块按照超级块、组描述符、块位图、inode位图、inode table、数据库的顺序构建。使用共用体包含上述每种块的数据结构。实现中涉及的块号用16位无符号short表示,该块组中最多不会超过2^16块。数据结构详情如下表:

image

其中,inode table是索引节点表,每个文件的inode使用128字节存储。inode table一共占用32块,每块顺序存储32个inode。因此规定,此系统最多不超过1024个文件或目录。Inode table的结构类似于二维数组,截取一行里的不同段表示不同的字段表示inode的不同属性。为了简便这里使用了结构体数组起到相似的功能。

数据块分为目录块和文件块。目录块和文件块的头2个字节都用作指针,指向同一文件的下一数据块, 若为0表示没有下一个数据块。文件块使用余下的4094字节来存储数据。目录块稍有特殊,使用第二个字存储自身的inode(即.目录),使用第三个字存储父目录的inode(即..目录)。目录块从第四个字开始存储自身包含的子目录的inode,每个inode用一个字(2字节)存储,依次排列。

建立系统时,初始化并建立了root根目录。Root目录的inode设为0,新建的文件或目录inode范围在1~1023之间。具体命令的实现**如下:

touch

找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有无重名文件。有重名文件时修改其inode,更新文件修改时间;无重名文件时查询组描述符,检查索引节点和存储空间是否有空闲。有空闲则开始创建文件。查询inode位图和数据位图,找到空闲的inode和数据块。向inode写入文件信息。若touch命令没有指定文件大小,则不申请数据块,只填写inode。

rm

找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有要删除的文件。若能通过文件名确定inode,则将相应位置的inode位图恢复为0,表示这个inode可以被新文件申请使用。然后将相应位置的数据位图恢复为0,若有后继数据块,重复恢复过程,直到所有用到的数据块位都恢复为0。并且,将父目录数据块里记录这一个文件inode的两个字节覆盖为0,从而使父目录不能再查询到这一子文件。rm的执行并不会删除inode节点和数据块里的内容,当有新文件使用它们时,才会将其清理。

ls

找到当前工作目录的数据块,每次读取两个字节,若不为0,则为一个子文件的inode,将其inode节点存储的文件名显示出来。直到该块被遍历完毕。若有后继块,则继续读取。使用-a选项时,额外打印隐藏的.和..目录。使用-l选项时,打印详细信息,将inode节点里的各个属性依次显示出来。

mkdir

找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有无重名目录。有重名文件时停止创建;无重名文件时查询组描述符,检查索引节点和存储空间是否有空闲。有空闲则开始创建该目录。查询inode位图和数据位图,找到空闲的inode和数据块。向inode写入目录信息,向数据块的前三个字分别写入0、自身的inode、父目录的inode。

rmdir

找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有要删除的目录。若能通过目录名确定inode,则将相应位置的inode位图恢复为0,表示这个inode可以被新文件申请使用。然后将相应位置的数据位图恢复为0,若有后继数据块,重复恢复过程,直到所有用到的数据块位都恢复为0。并且,将父目录数据块里记录这一个目录inode的两个字节覆盖为0,从而使父目录不能再查询到这一子目录。rm的执行并不会删除inode节点和数据块里的内容,当有新文件使用它们时,才会将其清理。

cd

程序使用一个全局变量now_dir记录当前工作目录的inode。可以通过递归查找目录的..目录(父目录),直到找到根目录来拼接成完整的路径。使用cd命令时只需要在当前目录数据块内查找到相应目录的inode,将now_dir变量更新为该inode后再次递归显示路径即可。

About

基于Linux的Ext2文件系统模拟


Languages

Language:C 100.0%