基于C++的模拟Unix文件系统

Ifyou

发布日期: 2019-04-14 23:23:57 浏览量: 376
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

一、实验介绍

本次实验的内容是完成一个 UNIX文件系统的子集的模拟实现。

实验要求:

  • 完成文件卷结构设计

  • I节点结构设计

  • 目录结构

  • 用户及组结构

  • 文件树结构

  • 实现功能如下命令:

    1. Ls 显示文件目录
    2. Chmod 改变文件权限
    3. Chown 改变文件拥有者
    4. Chgrp 改变文件所属组
    5. Pwd 显示当前目录
    6. Cd 改变当前目录
    7. Mkdir 创建子目录
    8. Rmdir 删除子目录
    9. Umask 文件创建屏蔽码
    10. Mv 改变文件名
    11. Cp 文件拷贝
    12. Rm 文件删除
    13. Ln 建立文件联接
    14. Cat 连接显示文件内容
    15. Passwd 修改用户口令

二、实验环境

  • 操作系统:windows 10 64位

  • 开发工具:visual studio 2017

  • 程序类型:win32 控制台应用程序

  • 引用库

    1. #include <iostream>
    2. #include <conio.h>
    3. #include <fstream>
    4. #include <time.h>
    5. #include <stack>
    6. #include <stdio.h>
    7. #include <windows.h>
    8. #include "dataStruct.h"
    9. #include "error.h"

三、实验设计

3.1 系统流程图

程序开始执行后,程序会先将资源文件读取,并以一文件指针保存在全局变量virtualDisk中。

读取文件成功以后,通过文件指针访问超级块所在盘块,读取内容保存在全局变量super中。

加载超级块以后,程序通过iget操作获取到root节点,保存在全局变量root中。

接下来,进入登录界面,用户输入密码和口令,程序根据用户的输入,读取用户文件,判断是否登录成功,成功以后进入程序的主界面。

3.2 文件卷设计

本程序的模拟磁盘的大小是8MB,每个盘块的大小设定为1KB,共8192个盘块。其中0号盘块在本程序中没有使用,但保留了下来。1号盘块保存超级块的信息。2-911盘块保存的是finode节点的信息。从912盘块开始,都是存储文件内容的盘块,使用成组链接法来管理,每组的盘块数是20。关于结点等数据结构会在下面部分详细介绍。

3.3 实现命令操作

本程序主要实现了以下的操作:

  1. Ls 显示文件目录
  2. Chmod 改变文件权限
  3. Chown 改变文件拥有者
  4. Chgrp 改变文件所属组
  5. Pwd 显示当前目录
  6. Cd 改变当前目录
  7. Mkdir 创建子目录
  8. Rmdir 删除子目录
  9. Mv 改变文件名
  10. Cp 文件拷贝
  11. Cat 连接显示文件内容
  12. Passwd 修改用户口令

此外本程序还额外完成了以下指令:

  1. touch 新建一个文件
  2. >> 向文件里面追加内容

指令的详细介绍和解释会在第五章模块详解中具体介绍。

四、数据结构

4.1超级快数据结构

1#块为超级块(superblock)。磁盘的回收和索引结点的分配与回收,将涉及到超级块。超级块是专门用于记录文件系统中盘块和磁盘索引节点使用情况的一个盘块,其中含有以下各个字段:

  • size:文件系统的盘块数

  • freeBlock:空闲盘块号栈,即用于记录当前可用的空闲盘块编号的栈

  • nextFreeBlock:当前空闲盘快号数,即在空闲盘块号栈中保存的空闲盘块号的数目。他也可以被视为空闲盘块号栈的指针

  • freeInode:空闲磁盘i结点编号栈,即记录了当前可用的素偶皮空闲结点编号的栈

  • nextFreeInode:空闲磁盘i结点数目,指在磁盘i结点栈中保存的空闲i结点编号的数目,也可以视为当前空闲i结点栈顶的指针

  • freeBlockNum:空闲盘块数,用于记录整个文件系统中未被分配的盘块个数

  • freeInodeNum:空闲i结点个数,用于记录整个文件系统中未被分配的节点个数

  • lastLogin:上次登录时间

  1. struct supblock
  2. {
  3. unsigned int size; //the size of the disk
  4. unsigned int freeBlock[BLOCKNUM]; //the stack of the free block
  5. unsigned int nextFreeBlock; //the pointer of the next free block in the stack
  6. unsigned int freeBlockNum; //the totally number of the free block in the disk
  7. unsigned int freeInode[INODENUM]; //the stack of the free node
  8. unsigned int freeInodeNum; //the totally number of the free inode in the disk
  9. unsigned int nextFreeInode; //the next free inode in the stack
  10. unsigned int lastLogin;
  11. };

4.2 结点数据结构

关于索引结点,本程序的主要由两种结构的定义,分别是内存索引结点和磁盘索引结点。

磁盘索引结点

  • mode:文件类型及属性

  • fileSize:文件大小

  • fileLink:文件连接数

  • owner:所属用户名

  • group:所属用户组

  • modifyTime:修改时间

  • createTime:创建时间

  • addr:盘块地址数组

结构定义

  1. struct finode
  2. {
  3. int mode;
  4. long int fileSize;
  5. int fileLink;
  6. char owner[MAXNAME];
  7. char group[GROUPNAME];
  8. long int modifyTime;
  9. long int createTime;
  10. int addr[6];
  11. char black[45]; //留空,以备内容扩充时不会影响结构大小
  12. };

内存索引结点

内存索引结点是保存在内存中索引结点的数据结构,当文件第一次被打开时,文件的索引结点从模拟磁盘上读出,并保存在内存中,方便下一次文件的打开。

  • finode:磁盘索引结点结构,保存从磁盘读出的索引结点信息

  • parent:父级内存索引结点指针

  • inodeID:索引结点号

  • userCount:用户打开数

结构定义

  1. struct inode
  2. {
  3. struct finode finode;
  4. struct inode *parent;
  5. unsigned short int inodeID; //the node id
  6. int userCount; //the number of process using the inode
  7. };

4.3 文件数据结构

文件目录项

文件目录项由文件名和文件索引结点号组成。

  • directName:文件名或目录名

  • inodeID:文件索引结点号

结构定义

  1. struct direct
  2. {
  3. char directName[DIRECTNAME];
  4. unsigned short int inodeID;
  5. };

4.4 目录数据结构

目录结构

  • dirNum:目录数目

  • direct:目录项数组

结构定义

  1. struct dir
  2. {
  3. int dirNum;
  4. struct direct direct[DIRNUM];
  5. };

对于目录类,它的内容都是以dir结构保存在磁盘中的,并以dir结构读取。

五、模块详解

5.1 文件操作

关于文件,本模拟系统主要实现了以下的操作:

  • Chgrp 改变文件所属组:

    • 命令格式
      • chgrp [组] [文件]
    • 命令功能
      • chgrp命令可采用群组名称或群组识别码的方式改变文件或目录的所属群组。使用权限是超级用户
    • 命令参数:

      • [组]:用户组名称
      • [文件]:文件名称
    • Chown改变文件拥有者:

    • 命令格式
      • chown [用户名][文件]
    • 命令功能
      • 通过chown改变文件的拥有者
    • 命令参数

      • [用户名]:要更改的新的用户名
      • [文件]:要修改的文件名
    • Chmod改变文件权限:

    • 命令格式
      • chmod [mode] [文件名]
    • 命令功能
      • chmod命令用于改变linux系统文件或目录的访问权限。用它控制文件或目录的访问权限
    • 命令参数
      • [mode] 文件权限码
        r=4,w=2,x=1
        若要rwx属性则4+2+1=7
        若要rw-属性则4+2=6;
        若要r-x属性则4+1=7。
      • [文件名] 要更改的文件名称
  • Rmdir删除文件(兼顾删除子目录功能):

    • 命令格式
      • rmdir 文件名/目录名
    • 命令功能
      • 该命令从一个目录中删除一个文件或者是目录项,若是目录项,目录项下的所有文件和目录也将被删除
  • Cat连接显示文件内容:

    • 命令格式
      • cat 文件名
    • 命令功能
      • cat命令的用途是连接文件并打印。这个命令常用来显示文件内容
  • Cp文件拷贝:

    • 命令格式
      • cp 源目的
    • 命令功能
      • cp命令用来复制文件或者目录,是UNIX系统中最常用的命令之一
    • 命令参数
      • 源:要复制的源文件
      • 目的:要复制的目的文件
  • touch新建一个文件:

    • 命令格式
      • touch 文件名
    • 命令功能
      • 用于创建一个新的不存在文件
  • 向文件里面追加内容:

    • 命令格式
      • 文件名 内容
    • 命令功能
      • 改指令用于向已尽存在的文件中追加内容,内容将会追加到问价你的末尾
  • mv修改文件名

    • 命令格式
      • mv 文件 新文件名
    • 命令功能
      • 改指令用于修改目录中已经存在文件名。

5.2 目录操作

关于目录,本模拟系统主要实现以下几个指令:

  • Ls显示文件目录:

    • 命令格式
      • ls
    • 命令功能
      • ls命令是UNIX下最常用的命令。ls命令就是list的缩写,用来打印出当前目录的清单
  • Pwd 显示当前目录:

    • 命令格式
      • pwd
    • 命令功能
      • pwd 命令来查看”当前工作目录“的完整路径。 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录。在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置
  • Cd 改变当前目录:

    • 命令格式
      • cd 目录名
    • 命令功能
      • cd指令的功能是进入目录,支持相对路径和绝对路径
  • Mkdir 创建子目录:

    • 命令格式
      • Mkdir 目录名
    • 命令功能
      • mkdir指令是用于在当前目录下创建子目录的指令
  • Rmdir 删除子目录:

    • 命令格式
      • rmdir 文件名/目录名
    • 命令功能
      • 该命令从一个目录中删除一个文件或者是目录项,若是目录项,目录项下的所有文件和目录也将被删除

5.3 主函数

主函数中,最最核心的函数就是dispatch函数,它解析用户输入的指令,并解析出参数,调用用户需要的函数。其流程图如下:

5.4 核心函数

一下函数为整一个文件系统最最核心的功能,所有的操作都是建立在以下函数的基础上进行的:

盘块读函数

  1. int bread(void * _Buf,unsigned short int bno,long int offset,int size,int count=1)

该函数将指定的盘块号内容的读取到对应的数据结构中。

盘块写函数

  1. int bwrite(void * _Buf,unsigned short int bno,long int offset,int size,int count=1)

该函数将指定数据的内容写入到指定的盘块中。

结点分配函数

  1. struct inode* ialloc()

该函数的作用是为从超级块的空闲结点栈中取出一个新的结点,并初始化该结点。其流程图如图5.4.1所示。

盘块分配函数

  1. int balloc()

该函数的主要功能是从超级快的空闲盘块栈中取出一个空闲盘块号,若栈只剩一个空闲盘块,那么采用成组链接法,读取下一组的空闲盘块栈。函数流程图如图5.4.2所示。

盘块回收函数

  1. int bfree(int bno)

该函数的主要功能是回收空闲盘块,若超级块中的空闲盘块栈未满,则回收盘块号入栈,若空闲盘块栈满,则将栈内容写到新回收的盘块上,清空栈,并将新的盘块号入栈。流程图如图5.4.3。

六、实验演示

6.1 进入文件系统

6.2 文件相关操作

创建一个文件并在目录上显示

向文件newtest.txt写入内容并链接显示内容

修改文件名称

6.3 目录相关操作

显示当前目录下的文件详细信息

显示当前目录路径

help命令

七、实验总结

本次实验对自己来说是一个很大的挑战,看了很多的资料,书上和网上的技术博客,虽说不完全是自己写的代码,但是自己有很用心去读懂它,看懂它。通过这次实验,我了解操作体统中,文件是如何进行管理和规划。知道了结点,盘块的概念,了解了文件的组织结构,这对于未来我从事计算机底层开发来说意义重大。

上传的附件 cloud_download 基于C++的模拟Unix文件系统.7z ( 1.08mb, 1次下载 )
error_outline 下载需要11点积分

发送私信

一个人害怕的事,往往是他应该做的事

11
文章数
14
评论数
最近文章
eject