-
与用户交互,在内存中开辟空间来模拟文件系统的运行
-
实现了
touch
、rm
、ls
、mkdir
、cd
等Linux文件操作命令 -
基于Linux的inode(索引节点)与位图技术
1、在内存中开辟一块空间来模拟文件系统的运行,不读写硬盘。
2、面向单用户、单任务,不考虑并发,不考虑文件属主、组等概念。
3、程序开始后,初始化并接收用户输入。若输入”enter”,则重新建立文件系统, 读取上次的退出状态,以上次目录为当前目录; 若输入”q”则退出程序。
系统采用命令行方式与用户交互:touch
, rm
, ls
, mkdir
, rmdir
, cd
;显示每条命令的执行结果;然后准备接收下一条命令。
用户输入”exit”后,保存当前状态,退出系统 ,等待用户输入。
文件名(最大长度?) ;
文件类型:目录、数据;不考虑链接。
文件权限:w/r/x ;
文件大小:字节为单位。
文件最后修改时间:取程序运行来的时钟滴答数(转换为float)。
超级块:结构体;
组描述:结构体;
块位图:一维数组;
inode位图:一维数组;
inode table::二维数组,每行am位表示**,nx位表示**… ;
数据块:每个数据块的头2个字节作指针,指向同一文件的下一数据块。
数据文件:第一个数据块的地址在inode table 表项中,后续数据块通过指针连接起来;
目录文件:同上。每2个字节用来记录一个子inode。
存储空间组织:内存空间分成若干小块。
touch filename
:若filename不存在,则创建新数据文件,分配inode,不分配数据块;若filename存在,则修改文件时间。
touch size filename
: 若filename不存在,则创建新数据文件,分配inode,根据size分配数据块; 若filename存在,则修改文件大小和时间。
rm
删除一个文件,cd
改变工作目录,mkdir
创建一个目录文件,rmdir
删除一个空目录。所有命令都要有输出(结果或信息)。
在Ext2文件系统中的所有块组大小相同并被顺序存放。在本实验中,并没有设计完整分区,只设计了分区中的一个块组,大小128MB,组描述符也只占一个块。设计块大小为4KB,每个4KB的块位图描述32K个数据块,组成块组的总体大小128MB。
文件系统中的块按照超级块、组描述符、块位图、inode位图、inode table、数据库的顺序构建。使用共用体包含上述每种块的数据结构。实现中涉及的块号用16位无符号short表示,该块组中最多不会超过2^16块。数据结构详情如下表:
其中,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之间。具体命令的实现**如下:
找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有无重名文件。有重名文件时修改其inode,更新文件修改时间;无重名文件时查询组描述符,检查索引节点和存储空间是否有空闲。有空闲则开始创建文件。查询inode位图和数据位图,找到空闲的inode和数据块。向inode写入文件信息。若touch命令没有指定文件大小,则不申请数据块,只填写inode。
找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有要删除的文件。若能通过文件名确定inode,则将相应位置的inode位图恢复为0,表示这个inode可以被新文件申请使用。然后将相应位置的数据位图恢复为0,若有后继数据块,重复恢复过程,直到所有用到的数据块位都恢复为0。并且,将父目录数据块里记录这一个文件inode的两个字节覆盖为0,从而使父目录不能再查询到这一子文件。rm的执行并不会删除inode节点和数据块里的内容,当有新文件使用它们时,才会将其清理。
找到当前工作目录的数据块,每次读取两个字节,若不为0,则为一个子文件的inode,将其inode节点存储的文件名显示出来。直到该块被遍历完毕。若有后继块,则继续读取。使用-a选项时,额外打印隐藏的.和..目录。使用-l选项时,打印详细信息,将inode节点里的各个属性依次显示出来。
找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有无重名目录。有重名文件时停止创建;无重名文件时查询组描述符,检查索引节点和存储空间是否有空闲。有空闲则开始创建该目录。查询inode位图和数据位图,找到空闲的inode和数据块。向inode写入目录信息,向数据块的前三个字分别写入0、自身的inode、父目录的inode。
找到当前工作目录的数据块,找到所有子文件的inode。通过查询inode里存储的文件名,进行比对,确定有要删除的目录。若能通过目录名确定inode,则将相应位置的inode位图恢复为0,表示这个inode可以被新文件申请使用。然后将相应位置的数据位图恢复为0,若有后继数据块,重复恢复过程,直到所有用到的数据块位都恢复为0。并且,将父目录数据块里记录这一个目录inode的两个字节覆盖为0,从而使父目录不能再查询到这一子目录。rm的执行并不会删除inode节点和数据块里的内容,当有新文件使用它们时,才会将其清理。
程序使用一个全局变量now_dir记录当前工作目录的inode。可以通过递归查找目录的..目录(父目录),直到找到根目录来拼接成完整的路径。使用cd命令时只需要在当前目录数据块内查找到相应目录的inode,将now_dir变量更新为该inode后再次递归显示路径即可。