基于C++实现简易UNIX二级文件系统【100010622】

一、实验概述

1.1 实验目的

UNIX 文件系统提供了层次结构的目录和文件,负责系统内文件信息的管理,是 UNNIX 系统中极为重要的一个部分。本次实验的目的是通过模拟 UNIX V6++ 编写一个 UNIX 文件系统,实现基本文件操作,从而掌握 UNIX 文件系统结构。

1.2 实验要求

使用一个普通的大文件(如 c: myDisk.img,称之为一级文件)来模拟 UNIX V6++ 一个文件卷(把一个大文件当一张磁盘用)。

在这里插入图片描述

1.2.1 图 1: 文件卷结构

一个文件卷实际上就是一张逻辑磁盘,磁盘中存储的信息以块为单位,每块 512 字节。
基于C++实现简易UNIX二级文件系统【100010622】_第1张图片

1.2.2 图 2: 使用文件卷模拟逻辑磁盘

磁盘文件结构

  • 定义自己的磁盘文件结构
  • SuperBlock 结构
  • 磁盘 Inode 节点结构,包括:索引结构
  • 磁盘 Inode 节点的分配与回收算法设计与实现
  • 文件数据区的分配与回收算法设计与实现

文件目录结构

  • 目录文件结构
  • 目录检索算法的设计与实现

文件打开结构

磁盘高速缓存:选作

文件操作接口

  • fformat:格式化文件卷
  • ls :列目录
  • mkdir :创建目录
  • fcreat :新建文件
  • fopen :打开文件
  • fclose :关闭文件
  • fread :读文件
  • fwrite 写文件
  • flseek 定位文件读写指针
  • fdelete :删除文件
  • ……

主程序

  • 格式化文件卷

  • 用 mkdir 命令创建子目录,建立如图所示的目录结构
    基于C++实现简易UNIX二级文件系统【100010622】_第2张图片

图 3: 文件目录结构

  • 把你的课设报告,关于课程设计报告的 ReadMe.txt 和一张图片存进这个文件系统,分别放在/home/texts ,/home/reports 和 /home/photos 文件夹;

  • 图形界面或者命令行方式,等待用户输入;

  • 根据用户不同的输入,返回结果。

通过命令行方式测试

  • 新建文件 /test/Jerry ,打开该文件,任意写入 800 个字节;
  • 将文件读写指针定位到第 500 字节,读出 500 个字节到字符串 abc 。
  • 将 abc 写回文件。
  • 观察结果是否正确,并详细解释每一步的工作过程

1.3 设计报告要求

实验报告内容

  • 需求分析(10%):说明程序任务,包括输入、输出形式,程序功能。
  • 概要设计(15%):任务分解;数据结构定义;模块间的调用关系,算法说明等。
  • 详细设计(30%):重点函数的重点变量需说明,重点功能部分要绘制清晰的程序流程图。画出函数调用关系。

运行结果分析(30%):

  • 程序运行结果展示说明;
  • 测试命令及输出结果,结果分析。
  • 用户使用说明(5%)
  • 实验总结(5%):包括综合实验过程的收获、遇到问题及解决问题过程的思考、在综合实验过程中对课程的认识等内容。

评分标准

  • 视系统及实验报告的完成情况:不及格良
  • 加分项(完成下列内容之一)
    • 实现内存高速缓存,实验报告中需说明缓存数据结构与管理算法
    • 允许多个用户同时访问二级文件系统

1.4 实验环境

​ 操作系统:Windows 10 家庭版开发语言:C++ 编译器:Microsoft Visual Studio Community 2019

二、需求分析

2.1 程序输入形式

根据对题目要求分析和用户使用分析,文件系统采用控制台命令作为输入,按照系统给定的命令即可完成相应的功能。本文件模拟系统使用尽可能详细的控制台引导用户输入指令。

用户可以在控制台输入的指令如下:

  • HELP———–帮助文档。

  • ATTRIB———显示或更改文件属性。

  • CD————-显示当前目录的名称或将其更改。

  • DEL————删除至少一个文件。

  • DIR————显示一个目录中的文件和子目录。

  • EXIT———–退出文件系统。

  • MKDIR———-创建一个目录。

  • RMDIR———-删除目录。

  • PRINT———-打印文件内容。

  • WRITE———-向文件中写入内容

  • OPEN———–打开一个文件

  • CLOSE———-关闭一个文件

  • CREATE———创建一个文件

  • OPENLIST——-当前打开文件列表

  • FSEEK———-更改一个文件的指针

  • LOGOUT———用户退出登录

  • WHOAMI———显示当前用户信息

  • FORMAT———格式化文件卷

  • REGISTER——-用户注册

  • DELETEACCOUNT–删除用户(root 用户下)

  • SU————-改变用户

  • CHGRP———-改变用户所属组(root 用户下)

  • USERLIST——-显示所有用户信息(root 用户下)使用 help 命令查看各个指令的详细内容如下:

  • ATTRIB 显示或更改文件属性。

基于C++实现简易UNIX二级文件系统【100010622】_第3张图片

图 4: ATTRIB 指令

CD 显示当前目录的名称或将其更改。

基于C++实现简易UNIX二级文件系统【100010622】_第4张图片

图 5: CD 指令

DEL 删除至少一个文件。

基于C++实现简易UNIX二级文件系统【100010622】_第5张图片

图 6: DEL 指令

DIR 显示一个目录中的文件和子目录。

基于C++实现简易UNIX二级文件系统【100010622】_第6张图片

图 7: DIR 指令

EXIT 退出文件系统。

基于C++实现简易UNIX二级文件系统【100010622】_第7张图片

图 8: EXIT 指令

MKDIR 创建一个目录。

基于C++实现简易UNIX二级文件系统【100010622】_第8张图片

图 9: MKDIR 指令

RMDIR 删除目录。

在这里插入图片描述

图 10: RMDIR 指令

PRINT 打印文件内容。

基于C++实现简易UNIX二级文件系统【100010622】_第9张图片

图 11: PRINT 指令

WRITE 向文件中写入内容

基于C++实现简易UNIX二级文件系统【100010622】_第10张图片

图 12: WRITE 指令

OPEN 打开一个文件

基于C++实现简易UNIX二级文件系统【100010622】_第11张图片

图 13: OPEN 指令

CLOSE 关闭一个文件

基于C++实现简易UNIX二级文件系统【100010622】_第12张图片

图 14: CLOSE 指令

CREATE 创建一个文件

基于C++实现简易UNIX二级文件系统【100010622】_第13张图片

图 15: CREATE 指令

OPENLIST 当前打开文件列表

在这里插入图片描述

图 16: OPENLIST 指令

FSEEK 更改一个文件的指针

基于C++实现简易UNIX二级文件系统【100010622】_第14张图片

图 17: FSEEK 指令

LOGOUT 用户退出登录

在这里插入图片描述

图 18: LOGOUT 指令

WHOAMI 显示当前用户信息

在这里插入图片描述

图 19: WHOAMI 指令

FORMAT 格式化文件卷

在这里插入图片描述

图 20: FORMAT 指令

基于C++实现简易UNIX二级文件系统【100010622】_第15张图片

图 21: REGISTER 指令

DELETEACCOUNT 删除用户(root 用户下)

基于C++实现简易UNIX二级文件系统【100010622】_第16张图片

图 22: DELETEACCOUNT 指令

SU 改变用户

基于C++实现简易UNIX二级文件系统【100010622】_第17张图片

图 23: SU 指令

CHGRP 改变用户所属组(root 用户下)

基于C++实现简易UNIX二级文件系统【100010622】_第18张图片

图 24: CHGRP 指令

USERLIST 显示所有用户信息(root 用户下)

在这里插入图片描述

图 25: USERLIST 指令

2.2 程序输出形式

​ 程序通过控制台命令行交互的方式进行用户输入引导和显示反馈输出,具体输出将在后续进行介绍。

基于C++实现简易UNIX二级文件系统【100010622】_第19张图片

图 26: 程序输出

2.3 程序功能

实验模拟 UNIX 文件操作系统实现了多用户下文件的一系列操作。具体可以实现的功能如下所示:

  • 多用户下文件的创建、删除
  • 多用户下文件的打开、关闭、读、写、读写指针移动
  • 当前打开文件列表的显示
  • 多用户下更改文件读写属性(权限)
  • 多用户下目录的创建、删除
  • 多用户下目录的更改
  • 一个目录下文件和子目录的显示
  • 用户的创建、删除
  • 用户的登录、退出、更改
  • 修改用户所属组
  • 显示当前用户信息
  • 显示所有用户信息
  • 格式化文件卷
  • 退出文件系统
  • 帮助文档

三、概要设计

3.1 任务分解

​ 整个多用户文件系统可以划分为以下几个模块:

  • 内存管理模块:主要负责 SuperBlock、Inode、Block 的初始化、申请和释放。提供读入读出 SuperBlock、Inode、Block 块以及申请释放 Block 块的接口,同时提供每个 Inode 中逻辑 Block 块号和物理 Block 块号映射关系转换接口。

  • 文件管理模块:主要负责文件相关的一系列操作。提供创建文件、删除文件、显示文件列表、打开文件关闭文件、写文件、读文件、更改文件指针、更改文件权限等操作的相关接口。

  • 用户管理模块:主要负责用户相关的一系列操作。提供用户登录、用户登出、创建用户、删除用户、获取当前登录用户信息、更改用户所属组、输出用户列表信息等操作的相关接口。

  • 目录管理模块:主要负责文件目录相关的一系列操作。提供创建目录、删除目录、打开目录、获取当前目录等操作的相关接口

  • 顶层管理模块:主要负责用户输入信息处理、将用户输入命令转化为内核操作、反馈信息输出、错误反馈等。

3.2 数据结构定义

整个文件系统包含以下几个数据结构的定义:

  • Inode 结构体:

Inode 结构体中存储一个 Inode,大小为 64 字节,4 个 Inode 占满一个 BLock 块。其内部有两个枚举类型 INodeMode 和 INodePermission,分别用于枚举 Inode 指向的为文件还是目录、该目录/文件的读写属性,其中读写属性分为文件主、文件主同组和其他用户三组,OWNER_R 为文件主可读,OWNER_W 为文件主可写,OWNER_E 为文件主可执行,GROUP_R 为文件主同组可读,GROUP_W 为文件主同组可写,

GROUP_E 为文件主同组可执行,ELSE_R 为其他用户可读,ELSE_W 为其他用户可写,ELSE_E 为其他用户可执行。

Inode 结构体主要包含的成员如下:i_addr 用于文件逻辑块和物理块的映射,其映射关系如图 27 所示,最多可以容纳 1281282+128*2+6 个 Block 块。i_size 存储文件大

小,以自己为单位,目录大小统一设置为 0,i_count 为当前文件被打开的引用计数, i_number 为当前 Inode 的编号,i_permission 为文件的读写权限,其值为 OWNER_R、 OWNER_W、OWNER_E、GROUP_R、GROUP_W、GROUP_E、ELSE_R、ELSE_W、 ELSE_E 的组合,当 i_permission 与这几个值与运算后不为 0,则代表当前 Inode 拥有这一权限,i_uid 为文件/目录创建者用户 id,i_gid 为文件/目录创建者用户组 id, i_time 为文件最后访问时间。

基于C++实现简易UNIX二级文件系统【100010622】_第20张图片

图 27: i_addr 索引图

//Inode 结构体 struct	Inode {
    enum INodeMode {
        IFILE = 0x1,  //是文件
        IDIRECTORY = 0x2//是目录
    };
    enum INodePermission {//分为文件主、文件主同组和其他用户
        OWNER_R = 0400,
        OWNER_W = 0200,
        OWNER_E = 0100,
        GROUP_R = 040,
        GROUP_W = 020,
        GROUP_E = 010,
        ELSE_R = 04,
        ELSE_W = 02 ,
        ELSE_E = 01 ,
    };
        unsigned int i_addr [NINODE] ; //逻辑块号和物理块号转换的索引表
        unsigned	int	i_size ; //文件大小,字节为单位
        unsigned	short	i_count ; //引用计数
        unsigned	short	i_number ; //Inode 的编号
        unsigned	short	i_mode ; //文件工作方式信息
        unsigned	short	i_permission ; //文件权限
        unsigned	short	i_uid ; //文件所有者的用户标识
        unsigned	short	i_gid ; //文件所有者的组标识
};	
time_t i_time ; //最后访问时间   
  • SuperBlock 结构体

    SuperBlock 结构体中存储整个文件的 SuperBlock(文件系统超级块)。其中包含以下成员:s_inodenum 存储 Inode 总数,s_finodenum 存储空闲 Inode 数,s_blocknum 存储 Block 总数,s_fblocknum 存储空闲 Block 数,s_nfree 和 s_free 通过成组链接法管理所有空闲 Block,每一组的最大空闲 Block 数为 50(其中 0 号位用于存储下一个空闲表位置)。

// SuperBlock 结构体 
struct	SuperBlock { 
    				unsigned	short s_inodenum ; //Inode 总数 
                    unsigned	short	s_finodenum ; //空闲 Inode 数 
                    unsigned	short s_blocknum ; // Block 总数 unsigned	
                    short	s_fblocknum ; //空闲 Block 数 
                    unsigned	int	s_nfree ; //直接管理的空闲块数 
                    unsigned	int	s_free [FREE_BLOCK_GROUP_NUM] ; //空闲块索引表
};
  • Directory 结构体

Directory 结构体用于存储目录列表,对于一个 i_mode 为 IDIRECTORY 的 Inode,其 i_addr[0] 中所指向的 Block 存储一个 Directory,该 Directory 结构体中的信息即为该目录的信息。

Directory 结构体有两个成员 d_inodenumber 和 d_filename,分别用于存储该目录下的文件/目录的 Inode 号和名称。

// Directory 结构体 
struct	Directory { 
    unsigned	int	d_inodenumber [SUBDIRECTORY_NUM] ; //子目录Inode 号 
    char d_filename [SUBDIRECTORY_NUM] [FILE_NAME_MAX] ; //子目录文件名
};
  • User 结构体

User 结构体中存储所有的用户信息。User 结构体放置在 1 号 Block 中。

User 结构体包含四个成员:u_id 存储用户 id、u_gid 存储用户所在组 id、u_name 存储用户名、u_password 存储用户密码。用户 i 信息不存在时则 u_name[i] 为空。

//User 结构体 
struct	User { 
    		  unsigned	short u_id [USER_NUM] ; //用户 id unsigned	
              short u_gid [USER_NUM] ; //用户所在组 id 
              char u_name[USER_NUM] [USER_NAME_MAX] ;	//用户名 
              char u_password [USER_NUM] [USER_PASSWORD_MAX] ;	//用户密码
};
  • File

结构体

File 结构体存储打开文件信息。其包含的成员如下:f_inodeid 为文件的 inode 编号、

f_offset 为文件的读写指针位置、f_uid 为文件打开用户。File 结构体伴随打开文件和关闭文件存在消失。

// File 结构体 
struct	File { 
    		  unsigned	int	f_inodeid ; //文件的 inode 编号 
              unsigned	int	f_offset ; //文件的读写指针位置 
              unsigned	int	f_uid ; //文件打开用户
};

3.3 模块间调用关系

文件系统 myDisk.img 的空间分配如图 28 所示

基于C++实现简易UNIX二级文件系统【100010622】_第21张图片

图 28: myDisk.img 的空间分配

各个模块之间的调用关系如图 29 所示:

基于C++实现简易UNIX二级文件系统【100010622】_第22张图片

图 29: 模块间调用关系图

3.4 算法说明

整个算法的整体流程如图所示:

基于C++实现简易UNIX二级文件系统【100010622】_第23张图片

图 30: 整体流程图其中,根据命令执行操作的流程具体如下:

  • HELP

根据 help 后有无参数以及参数名,选择不同的提示输出。(具体可参考 2 需求分析模块)

  • ATTRIB

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Edit_File_Permission 函数更改文件权限。

  • CD

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则:如果 cd 后有参数,则根据参数调用 Open_Directory 函数更改文件目录,如果 cd 后无参数,则输出当前所在目录。

  • DEL

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数逐一调用 Delete_File 函数删除文件。

  • DIR

    首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用Show_File_List 函数显示文件信息。

  • EXIT

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则退出程序。

  • MKDIR

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Create_Directory 函数创建文件。

  • RMDIR

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Remove_Directory 函数删除目录。

  • PRINT

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Read_File 函数将文件内容读出到文件或屏幕。

  • WRITE

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Write_File 函数将文件或屏幕内容写入文件。

  • OPEN

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Open_File 函数打开文件。

  • CLOSE

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Close_File 函数打开文件。

  • CREATE

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Create_File 函数打开文件。

  • OPENLIST

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则遍历输出所有打开文件信息。

  • FSEEK

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Seek_File 函数更改文件指针。

  • LOGOUT

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则调用 User_Logout 函数使用户登出。

  • WHOAMI

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则调用 Get_User 函数输出当前用户信息。

  • FORMAT

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则调用 Init 函数初始化文件卷。

  • REGISTER

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

User_Register 函数进行用户注册。

  • DELETEACCOUNT

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

User_Delete 函数删除文件。

  • SU

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

User_Logout 函数和 User_Login 函数更改用户。

  • CHGRP

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Change_User_Group 函数更改用户组。

  • USERLIST

首先检查命令输入的正确性,若不正确则输出错误信息,若输入正确则根据参数调用

Show_User_List 函数展示用户表。

四、详细设计

顶层管理模块所涉及的部分已在前几部分进行了一定说明,下面对内存管理模块、目录管理模块、文件管理模块和用户管理模块的详细设计进行说明。

4.1 内存管理模块

4.1.1 内存块读写

  • 在文件操作的过程中,经常需要对 SuperBlock 块、Inode 块、User 表等部分进行读写,因
  • 此分离出 Read_SuperBlock、Write_SuperBlock、Read_InodeBitMap、Write_InodeBitMap、
  • Read_User、Write_User、Read_Inode、Write_Inode 几个函数对内存进行读写。

其流程图如图 31 所示:

基于C++实现简易UNIX二级文件系统【100010622】_第24张图片

4.1.1 图 31: 内存块读写

4.1.2 分配一个 Block 块

空闲盘块采用成组链接法进行管理(如图 32),其流程图如图 33 所示。

基于C++实现简易UNIX二级文件系统【100010622】_第25张图片

4.1.2 图 32: 成组链接法

基于C++实现简易UNIX二级文件系统【100010622】_第26张图片

图 33: 分配一个 Block 块

4.1.3 回收一个 Block 块

回收 Block 块为分配 Block 块的逆过程,两者流程相似。

//如果该空闲块已满,需要使 superblock 指向一个新的空块
i f	( superblock . s_nfree == FREE_BLOCK_GROUP_NUM  1) {
    fd . open(DISK_NAME,ios : : out	|	ios : : in | ios : :binary ) ;
    fd . seekg ((BLOCK_POSITION + block_num)  BLOCK_SIZE, ios : : beg ) ;
    fd . write (( char )&superblock . s_free, sizeof ( superblock . s_free ) ) ;
    fd . close () ;
    superblock . s_free [ 0 ] = block_num ;
    superblock . s_nfree = 0;
    superblock . s_fblocknum++;
}
else	{
    superblock . s_nfree++;
    superblock . s_free [ superblock . s_nfree ] = block_num ;
}

4.1.4 Inode 中逻辑块号与物理块号的映射

小型文件的索引结构

小型文件使用文件素引表中 i_addr[0]-i_addr[5] 这 6 项作为直接索引表,也就相当于限制了小型文件长度范围是 0-6 个数据块,每个盘块大小等于 512 字节。其中,文件逻辑块号 n 对应的物理块号记录在 i_addr[n] 中。譬如,i_addr[2] 的值为 2058 表示该文件的第 3 块数据 (偏移量 1024 1535 字节) 占据的物理盘块编号为 2058。

大型文件的索引结构

当文件的长度超出小型文件限制时,就需要采用大型文件的素引结构。大型文件除了使用 i_addr[0]-i_addr[5] 记录该文件前 6 个物理块号之外,还用到 i_addr[6]、i_addr[7] 两项,每一项指向一个含有物理块号明细的一次间接索引表块,每个一次间接索引表块可以容纳 512/4-128 个物理块号, 可为 128 个文件的逻辑块和物理块建立对应关系。

因此大型文件的长度范围是 7 (6+ 128 *2) 个数据块。如果内核需要通过一次间接索引表块访问数据, 那么先要将一次间接索引表块读入内存,从中找到逻辑块号对应的物理块号,然后再读取该物理块上的文件数据。

巨型文件的索引结构

如果文件长度比大型文件还要大,则除了用到基本素引表中的 i_addr[0]-i_addr[5] 以及

i_addr[6]、i_addr[7] 两项记录该文件前 128 2+6 个物理块号之外, 还要使用 i_addr[8]、 i_addr[9] 来记录二次间接索引表块的物理共号。二次间接索引表块的作用类似于一次间接索引表,表中的每一项都记录者它所指向的一个一次间接索引表块的物理块号,然后再由该一次间接索引表块中的各项记录文件数据的物理块号。每张二次间接索引表块最多可记录 128 个一次间接索引表的物理块号,因此巨型文件的长度范围为(1282+7) (1281282+1282+6)。

4.2 目录管理模块

4.2.1 创建目录

​ 创建目录的流程图 34 如图所示,创建目录成功的前提是目录名合法、有空闲的 block 和 inode、当前目录不存在同名目录、当前目录的文件数量未达到限制

基于C++实现简易UNIX二级文件系统【100010622】_第27张图片

4.2.1 图 34: 创建目录流程图

4.2.2 删除目录

删除目录的流程图如图 35 所示,删除目录的前提是目录名合法、目录为空。

基于C++实现简易UNIX二级文件系统【100010622】_第28张图片

4.2.2 图 35: 删除目录流程图

4.2.3 打开目录

打开一个目录需要根据目录路径一级级进入相应的位置,目录路径使用’ 或 ’/’ 进行分割,’.’ 代表当前目录,’…’ 代表父目录,根据目录名寻找到 Inode 号进而更改对应的 directory 即可完成目录的切换

4.2.4 获取当前目录

从当前目录向上级目录一层层进行寻找,并使用’ 进 行连接,即可完成当前目录的获取

4.3 文件管理模块

4.3.1 创建文件

创建文件的流程图如图所示,创建文件成功的前提是文件名合法、有空闲的 block 和 inode、当前目录不存在同名文件、当前目录的文件数量未达到限制

基于C++实现简易UNIX二级文件系统【100010622】_第29张图片

图 36: 创建文件流程图

4.3.2 更改文件指针

在保证当前用户为文件打开用户、用户具有写权限的前提下更改 File 结构体中的 file-

>f_offset 即可

4.3.3 读文件

在保证当前用户为文件打开用户、用户具有写权限的前提下,从 file->f_offset 指定位置开始依次取出 Block 块,直至读出文件长度等于 length 或读到文件末尾,在字符串末尾补尾零并返回读到字符串的长度。

4.3.4 更改文件权限

每个文件的权限共有三组,分别为主用户、同组用户、和其他用户,每一组用户权限又分为读权限、写权限以及执行权限,在相应的 Inode 中修改 i_permission 属性即可对该权限进行修改。

4.3.5 删除文件

删除文件的流程图如图所示,删除目录的前提是文件名合法、文件未被打开。

基于C++实现简易UNIX二级文件系统【100010622】_第30张图片

4.3.5 图 37: 删除文件流程图

4.3.6 打开文件

首先检查文件名是否合法,如果合法则在当前目录下寻找这一文件,找到后新建 File 结构体,在其中赋值 f_inodeid 为找到的 inode_num,f_offset 为 0,f_uid 为打开文件的用户 id,并返回 file 结构体。

4.3.7 写文件

写文件的流程如图所示,写文件需要保证当前用户为文件打开用户,用户具有写权限。

基于C++实现简易UNIX二级文件系统【100010622】_第31张图片

图 38: 写文件流程图

4.4 用户管理模块

4.4.1 登录用户

检查用户名和密码,若均正确,即可进行登录,若输入用户名错误,则提示此用户不存在,若输入密码错误,则输出密码错误

4.4.2 退出登录

将全局的 user_id 改为-1,即可完成用户登录的退出

4.4.3 创建用户

只有 root 用户可以进行用户的注册,注册前需要先检查该用户名是否已经存在,若存在,则给出报错,否则进行用户的新建。

4.4.4 删除用户

只有 root 用户可以进行用户的删除,删除前需要先检查该用户是否存在,若存在则进行用户的删除,否则给出报错。

4.4.5 改变用户所属组

只有 root 用户可以进行用户所属组的更改,更改前需要先检查该用户是否存在,若存在则进行用户的所属组更改,否则给出报错。

五、运行结果分析

5.1 运行结果

5.1.1 在初次打开 exe,文件系统不存在的情况下,会提示用户进行文件系统的初始化

基于C++实现简易UNIX二级文件系统【100010622】_第32张图片

5.1.2 图 39: 初始界面

随后提示需要进行登录,并输入用户名和密码,默认情况下存在两个用户:root 用户

拥有最高权限)、juju 用户(普通用户),此时使用 root 用户登录

5.1.3 图 40: 成功登录

基于C++实现简易UNIX二级文件系统【100010622】_第33张图片

对一些基本命令进行测试(详细测试将在下一部分进行展示):

基于C++实现简易UNIX二级文件系统【100010622】_第34张图片

图 41: 用户相关命令

基于C++实现简易UNIX二级文件系统【100010622】_第35张图片

图 42: help 命令

基于C++实现简易UNIX二级文件系统【100010622】_第36张图片

图 43: 文件及目录相关测试

5.2 命令测试

5.2.1 课设要求测试

用 mkdir 命令创建子目录,建立如图所示的目录结构;

基于C++实现简易UNIX二级文件系统【100010622】_第37张图片

图 44: 目录结构-1
在这里插入图片描述

图 45: 目录结构-2

把你的课设报告,关于课程设计报告的 ReadMe.txt 和一张图片存进这个文件系统,分别放在/home/texts ,/home/reports 和 /home/photos 文件夹;使用如下的命令将 ReadMe.txt 放入/home/texts

cd home/ texts
create	readme . txt open readme . txt
1 2 3

基于C++实现简易UNIX二级文件系统【100010622】_第38张图片

图 48: 放入 report.pdf

write readme . txt f ReadMe. txt close readme . txt
4 5

在这里插入图片描述

图 46: 将 ReadMe.txt 放入/home/texts

使用如下的命令将 readme.txt 中的内容再次写出:

cd home/ texts open readme . txt
print readme . txt p tmp. txt fseek readme . txt 0 close readme . txt
1 2 3 4 5

比对两个文件,完全一致,证明了程序的正确性。

基于C++实现简易UNIX二级文件系统【100010622】_第39张图片

  • 图 47: 文件比对
  • 进一步进行其他两个文件的放入
  • 新建文件 /test/Jerry ,打开该文件,任意写入 800 个字节;

基于C++实现简易UNIX二级文件系统【100010622】_第40张图片

  • 图 49: 创建文件并写入 800 字节
  • 由图 49,成功创建文件并进行了写入。
  • 将文件读写指针定位到第 500 字节,读出 500 个字节并写回到文件

基于C++实现简易UNIX二级文件系统【100010622】_第41张图片

图 50: 定位读写指针并写回文件

可以看到与预期相同,写入了 300 个字节

基于C++实现简易UNIX二级文件系统【100010622】_第42张图片

图 51: jerryfile.txt

再将其写回到文件

基于C++实现简易UNIX二级文件系统【100010622】_第43张图片

图 52: 写回文件

可以看到与预期相同,jerry 目前共由 1100 个字节

5.2.2 命令逐条测试

对命令进行逐一测试:

HELP———–帮助文档。

基于C++实现简易UNIX二级文件系统【100010622】_第44张图片

图 53: help 命令测试

ATTRIB———显示或更改文件属性。

基于C++实现简易UNIX二级文件系统【100010622】_第45张图片

图 54: 更改文件读写属性

CD————-显示当前目录的名称或将其更改。

在这里插入图片描述

图 55: 更改目录

DEL————删除至少一个文件。

基于C++实现简易UNIX二级文件系统【100010622】_第46张图片

图 56: 删除文件

DIR————显示一个目录中的文件和子目录。

基于C++实现简易UNIX二级文件系统【100010622】_第47张图片

图 57: 显示目录中内容

MKDIR———-创建一个目录。

基于C++实现简易UNIX二级文件系统【100010622】_第48张图片

图 58: 创建目录

RMDIR———-删除目录。
基于C++实现简易UNIX二级文件系统【100010622】_第49张图片

图 59: 删除目录

PRINT———-打印文件内容。

在这里插入图片描述

图 60: 打印文件内容

WRITE———-向文件中写入内容

在这里插入图片描述

图 61: 向文件写入

OPEN———–打开一个文件

在这里插入图片描述

图 62: 打开文件

CLOSE———-关闭一个文件

在这里插入图片描述

图 63: 关闭文件

CREATE———创建一个文件

基于C++实现简易UNIX二级文件系统【100010622】_第50张图片

图 64: 创建一个文件

OPENLIST——-当前打开文件列表

在这里插入图片描述

图 65: 打开文件列表

FSEEK———-更改一个文件的指针

基于C++实现简易UNIX二级文件系统【100010622】_第51张图片

图 66: 更改文件定位指针

LOGOUT———用户退出登录

在这里插入图片描述

图 67: 用户登出

WHOAMI———显示当前用户信息

基于C++实现简易UNIX二级文件系统【100010622】_第52张图片

图 68: 显示当前用户信息

REGISTER——-用户注册(root 用户下)

基于C++实现简易UNIX二级文件系统【100010622】_第53张图片

图 69: 用户注册

DELETEACCOUNT–删除用户(root 用户下)

基于C++实现简易UNIX二级文件系统【100010622】_第54张图片

图 70: 删除用户

SU————-改变用户

基于C++实现简易UNIX二级文件系统【100010622】_第55张图片

图 71: 改变用户

CHGRP———-改变用户所属组(root 用户下)

基于C++实现简易UNIX二级文件系统【100010622】_第56张图片

图 72: 改变用户所属组

USERLIST——-显示所有用户信息(root 用户下)

在这里插入图片描述

图 73: 显示用户信息

5.2.3 其他测试

多用户读写测试

– 首先,用户 juju 在文件 test.txt 中写入 juju

基于C++实现简易UNIX二级文件系统【100010622】_第57张图片

5.2.3 图 74: 多用户读写测试-1

– 随后用户 root 打开同一个文件 test.txt,在其中写入 root

基于C++实现简易UNIX二级文件系统【100010622】_第58张图片

5.2.3 图 75: 多用户读写测试-2

可以看到,root 用户在刚进入文件系统时可以看到 juju 写入的 4 个字节,随后 root 用户写入 root 将 juju 覆盖

– 此时 juju 再次进行文件的读,读到的是 root 用户写入的 root

基于C++实现简易UNIX二级文件系统【100010622】_第59张图片

5.2.3 图 76: 多用户读写测试-3

– juju 继续向文件中写入 juju

基于C++实现简易UNIX二级文件系统【100010622】_第60张图片

5.2.3 图 77: 多用户读写测试-4

– 此时 root 用户再次读

基于C++实现简易UNIX二级文件系统【100010622】_第61张图片

5.2.3 图 78: 多用户读写测试-5
  • 由图可知,juju 写入的 juju 四个字符已被 root 用户读到,因此可以得出结论,该文件系统支持多个用户同时读写。
  • 大文件读写
  • 从网上下载简爱英文版

基于C++实现简易UNIX二级文件系统【100010622】_第62张图片

  • 图 79: txt 格式简爱
  • 可以看到其共有 287871 字节
  • 将其写入文件

基于C++实现简易UNIX二级文件系统【100010622】_第63张图片

图 80: 大文件测试-1

将其读出到屏幕

基于C++实现简易UNIX二级文件系统【100010622】_第64张图片

图 81: 大文件测试-2

将输出内容与文件进行比对,两者完全相同

基于C++实现简易UNIX二级文件系统【100010622】_第65张图片

图 82: 大文件测试-3 因此可以得出结论,该系统可以进行大文件的读入

读写权限测试

root 用户创建文件,并更改其权限为除自己与同组用户外都不可读写

基于C++实现简易UNIX二级文件系统【100010622】_第66张图片

5.2.3 图 83: 读写权限测试-1

在这里插入图片描述

5.2.3 图 84: 读写权限测试-2

– 切换到 juju 用户(与 root 非同组)

基于C++实现简易UNIX二级文件系统【100010622】_第67张图片

图 85: 读写权限测试-3 可以看到,系统提示 juju 无权进行写操作

5.3 结果分析

由 5.1 及 5.2 可知,程序具有正确的运行结果,并在用户命令输入不当时可以进行正确的报错,同时可以对用户输入命令给予良好的引导,整个程序完整清晰,具有友好性和正确性

六、用户使用说明

项目结构:

基于C++实现简易UNIX二级文件系统【100010622】_第68张图片

图 86: 项目结构

运行方法:

在 Windows 下直接点击生成的 exe 文件执行,Linux 下可以将源程序放在集成环境下编译,也可利 GNU 编译工具,通过写好的 Makefile 进行编译。运行界面为控制台的命令行方式,命令较为简单,通俗易懂,初始界面如下:

基于C++实现简易UNIX二级文件系统【100010622】_第69张图片

​ 图 87: 初始界面

​ 具体命令的使用方法可以通过输入 [ help 命令名] 进行查看

​ 系统初始化后的文件结构如下:root –bin –etc –home —-texts —-reports —-photos –dev 最初进入系统时包含两个用户:root 用户和 juju 用户,其中 root 用户为最高权限用户,可以进行注册用户、删除用户、改变用户所属组、显示用户信息等操作,juju 为普通用户, root 用户密码为 root,juju 用户密码为 juju

​ 该文件系统在节点数量等上具有一定限制,用户的最大数量为 6,文件及目录个数最多为 256,一个目录下的子目录与文件数之和最多为 12,文件名称的最大长度为 32,用户名称的最大长度为 16,用户密码的最大长度为 32 程序正常退出使用 exit 命令,格式化使用 format 命令。

♻️ 资源

基于C++实现简易UNIX二级文件系统【100010622】_第70张图片

大小: 5.59MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87415717

你可能感兴趣的:(课程设计,unix,c++,服务器)