操作系统课程设计——文件管理模拟 C++版

06-11 1441阅读

参考博客:【操作系统之模拟文件管理系统 - CSDN App】

并在此基础上进行了修改和完善部分代码

这是我的第一篇CSDN,内容有点长


实验内容

文件管理

一、目的

通过模拟磁盘,完成操作系统的文件管理功能,掌握包括目录结构的管理、外存空【操作系统之模拟文件管理系统 - CSDN App】间的分配与释放以及空闲空间管理三部分。为写入模拟磁盘的数据文件建立目录,目录可以是单级文件目录、双级文件目录、树形结构目录。在目录中选择某个文件可以将其数据读入模拟内存。

二、设计内容

  1. 通过初始化操作建立一个模拟磁盘,在模拟磁盘中保存目录和文件内容。创建该模拟磁盘时可创建初始的根目录内容、文件分配表。
  2. 文件目录项(可以采用FCB格式)应包括文件名、类型(目录 or文件)、创建日期、大小、第一个磁盘块块号。
  3. 目录管理需支持:

    新建目录:在目录中新建空目录; 删除目录:删除空目录

    为文件建立目录项:一个文件创建成功后,为该文件创建目录项,并将文件和相关信息写入目录;

    删除文件:删除目录中某个文件,删除其在磁盘中的数据,并删除目录项。如果被删除文件已经读入内存应阻止删除,完成基本的文件保护。

三、 设计要求

  1. 不同的功能使用不同的函数实现(模块化),对每个函数的功能和调用接口要注释清楚。对程序其它部分也进行必要的注释。
  2. 对系统进行功能模块分析、画出总流程图和各模块流程图。
  3. 用户界面要求使用方便、简洁明了、美观大方、格式统一。所有功能可以反复使用,最好使用菜单。
  4. 通过命令行相应选项能直接进入某个相应菜单选项的功能模块。
  5. 所有程序需调试通过。

实验说明

本实验是参考了http://t.csdnimg.cn/B0Fqh

 ,并在此基础上进行了修改和完善部分代码。

本次实验为Linux系统设计了一个简单的二级文件系统,可以做到以下几点:

  1. 可用命令及说明
    • register 用户的注册
    • login 用户的登入
    • cd 切换目录
    • mkdir 创建用户的子目录
    • rmdir 删除用户的子目录
    • dir 显示当前目录的子目录
    • create 创建文件夹的文件
    • del 删除文件夹的文件
    • open 打开文件
    • close 关闭文件
    • read 读文件
    • write 写文件
    • set 设置文件的保护码
    • exit 退出系统
    • look 查看系统中的所有用户
    • fatused 查看目前块的状态
  2. 用户登入时会对用户名和密码进行匹配
  3. 进入系统的第一步需要注册账号并登入(为测试方便,初始化了一个用户)
  4. 在创建子目录时必须先登入
  5. 不可在打开的状态下进行任何删除操作
  6. 删除子目录或文件时释放其空间
  7. 创建文件和打开文件时必须先进入文件夹
  8. 文件被打开后可进行读写操作
  9. 文件保护码为2可读可写,为0不可读,其他不可写

文件结构

这些图表是我的一点理解,可能存在偏差

用户文件结构

操作系统课程设计——文件管理模拟 C++版

打开文件结构

操作系统课程设计——文件管理模拟 C++版

创建文件流程图

操作系统课程设计——文件管理模拟 C++版

删除文件流程图

操作系统课程设计——文件管理模拟 C++版

代码说明

整体结构

#define BLOCK_SIZE     		512  //每一个磁盘块的大小
#define BLOCK_NUM       	64   //磁盘块数量
#define MAX_FILE_NUM		16   //每个文件夹的最大文件数
#define MAX_FOLDER_NUM  	16	 //每个用户可以拥有的最大文件夹数
#define MAX_OPEN_FILE_NUM   16	 //最大同时打开文件数
#define MAX_USER_NUM		16   //最大用户数
  • 主目录
    • 存放用户数据结构 最大可存放16个用户
    • 用户名
    • 密码
    • 指向用户的指针
    struct MFD//用户数据结构
    {
    string username;//用户名
    string password;//密码
    struct USER_UFD *next;//指向用户文件的指针
    };
    • 子目录(文件夹数据结构)

      • 各个用户所拥有的目录
      • 最大创建16个目录(及文件)
      • 其中包含文件数据结构
      • 文件夹名字
      • 当前文件夹的文件数
    • 文件数据结构

      • 文件名(同文件下不可重名)
      • 文件保护码(默认为2 可读可写,为0 不可读)
      • 文件长度(长度超过块的存储范围会找下一个块)
      • 文件起始地址
      • 文件创建日期
      • 是否占用
      struct UFD//文件夹数据结构 
      {
      	struct file_message//文件数据结构
      	{
      		string filename;//文件名
      		int protect_code;//文件保护码
      		int length;//文件长度
      		int addr;//文件起始地址
      		string time;	//日期时间,格式为yyyymmdd hhmmss
              int used;//是否被占用 0:空闲 1:占用
      	}ufd[MAX_FILE_NUM];//一个文件夹最对可以有16个文件
      	string directname;//文件夹名字
      	int cur_file_size = 0;//当前该文件夹含有的文件数量
      };
      • 打开的文件数据结构
        • 最多打开16个文件
        • 文件名字
        • 文件长度
        • 文件保护码
        • 文件起始地址
        • 当前打开的文件数量
        struct UOF//打开文件数据结构
        {
        	struct uof
        	{
        		string filename;//文件名字
        		int pointer;//文件长度
        		int protect_code;//文件保护码  默认2  2为可读可写  0为不可读  其余数字不可写
        		int addr;//文件起始地址
        	}uof[MAX_OPEN_FILE_NUM];//最多可以同时打开16个文
        	int cur_openfilesize = 0;//当前打开的文件数量
        };
        • 块号数据结构
          • 存放下一页的块号
          • 块号的状态 (1 占用; 0 空闲)
          struct fat//块号
          {
          	int next = -1;//存放下一页的块号,无为-1
          	int used = 0;  //used存在三种状态,1:被占用 0:空闲
          }fat[BLOCK_NUM];//最大为64
          • 用户文件数据结构
            • 包含文件夹数据结构
            • 当前拥有的文件夹数量
            struct USER_UFD//用户文件数据结构
            {
            	struct UFD direct[MAX_FOLDER_NUM];//一个用户最多可以有16个文件夹
            	int cur_user_direct_size = 0;//当前拥有的文件夹数量
            };

            定义属性及函数声明

            int mark = 1;
            struct USER_UFD cur_user_all_direct_array[MAX_USER_NUM];//用户文件数组 16
            struct MFD cur_user;//当前用户
            struct UOF * cur_opentable;//指向打开文件数组的指针
            char *fdisk;//模拟磁盘指针
            struct UOF openfile[MAX_OPEN_FILE_NUM];//每一个用户对应一个文件打开表对象,16
            struct MFD mfd[MAX_USER_NUM]; //16个用户
            int cur_user_size = 0;//记录当前用户的人数
            string path;
            int REGISTER();//注册用户
            int LOGIN();//登录用户
            int CREATE(string name);//创建文件
            int DELETE(string name);//删除文件
            int OPEN(string name);//打开文件
            int WRITE(string name);//写文件
            int READ(string name);//读文件
            int CLOSE(string name);//关闭文件
            int CD();//更改当前目录
            int MKDIR(string name);//创建文件夹
            int DIR();//显示当前目录的子目录
            int SET(string name, int protectcode);//设置保护码
            void INPUT_OPERATION();//指令输入

            main函数

            初始化一个用户方便调试代码

            并输出命令格式说明

            int main()
            {
            	cur_user.username = "";
            	path = "";
            	fdisk = (char *)malloc(1024 * 1024 * sizeof(int));//模拟硬盘指针
            	
            	//注册root用户并登录,方便调试代码
            	mfd[cur_user_size].username = "root";
            	mfd[cur_user_size].password = "123456";
            	cur_user_size++;
            	mfd[0].next = &(cur_user_all_direct_array[0]);	
            	cur_user = mfd[0];
            	cur_user.next->cur_user_direct_size = mfd[0].next->cur_user_direct_size;
            	cur_user_size++;
            	cur_opentable = &openfile[cur_user_size]; //指针指向文件打开表对象
            	cur_opentable->cur_openfilesize = 0;
            	
            	cout 0};
            	strftime(ch, sizeof(ch) - 1, "%Y-%m-%d %H:%M:%S", localtime(&t));
            	return ch;
            }
            h4 id="create%E5%87%BD%E6%95%B0%E5%88%9B%E5%BB%BA%E6%96%87%E4%BB%B6"CREATE函数(创建文件)/h4 blockquote olli必须先进入文件夹在创建文件/lili找到对应文件夹/lili判断文件是否重名/lili判断该文件夹中的文件是否满16个/lili判断是否有空闲块/lili条件满足创建,否则输出提示/li/ol /blockquote p更新文件数据,文件数量+1,磁盘块占用/p pre class="brush:python;toolbar:false"//创建文件 int CREATE(string name) { int index; if (path == "") { cout direct[index].ufd[cur_user.next->direct[index].cur_file_size - 1].length; cur_user.next->direct[index].ufd[i].protect_code = cur_user.next->direct[index].ufd[cur_user.next->direct[index].cur_file_size - 1].protect_code; cur_user.next->direct[index].cur_file_size--; //将该文件设置为占用 fat[cur_user.next->direct[index].ufd[i].addr].used = 1; //next为-1 说明没有下一页,此为最后一页 int temp = fat[cur_user.next->direct[index].ufd[i].addr].next; while (temp != -1)//删除该文件的内存空间 { fat[temp].used = 0; temp = fat[temp].next; } cout direct[index].cur_file_size) { cout uof[cur_opentable->cur_openfilesize].filename = AllName;//在打开的文件数组中加入该文件 cur_opentable->uof[cur_opentable->cur_openfilesize].protect_code = cur_user.next->direct[index].ufd[k].protect_code;//保护码 cur_opentable->uof[cur_opentable->cur_openfilesize].pointer = cur_user.next->direct[index].ufd[k].length; cur_opentable->uof[cur_opentable->cur_openfilesize].addr = cur_user.next->direct[index].ufd[k].addr;//起始地址 cur_opentable->cur_openfilesize++; //文件打开数量加1 cout = cur_opentable->cur_openfilesize) { cout uof[cur_opentable->cur_openfilesize - 1].filename; cur_opentable->uof[i].pointer = cur_opentable->uof[cur_opentable->cur_openfilesize - 1].pointer; cur_opentable->uof[i].protect_code = cur_opentable->uof[cur_opentable->cur_openfilesize - 1].protect_code; cur_opentable->uof[i].addr = cur_opentable->uof[cur_opentable->cur_openfilesize - 1].addr; cur_opentable->cur_openfilesize--; cout direct[index].directname)//在当前用户的文件夹中找到相应的文件 { break; } } int i; //判读文件是否打开 for (i = 0; i cur_openfilesize; i++) { if (cur_opentable->uof[i].filename == path + '/' + name)//循环打开的文件 break; } if (i >= cur_opentable->cur_openfilesize) { cout uof[fd].pointer == 0) last_block_res = BLOCK_SIZE; else if(cur_opentable->uof[fd].pointer % BLOCK_SIZE == 0) last_block_res = 0; else last_block_res = BLOCK_SIZE - (cur_opentable->uof[fd].pointer % BLOCK_SIZE); //首先填满最后一个磁盘块 if(last_block_res) { if(last_block_res direct[index].ufd[temp].length = cur_user.next->direct[index].ufd[temp].length + cin_len; //更新用户目录文件表 cout cur_openfilesize) { cout temp_path; if (temp_path == "..") { if(path == "") { cout direct[i].directname) break; } if (i >= cur_user.next->cur_user_direct_size) { cout cur_user_direct_size) { cout cur_user_direct_size].directname = name; cur_user.next->direct[cur_user.next->cur_user_direct_size].cur_file_size = 0; //新创建的目录里面的文件个数为0 cur_user.next->cur_user_direct_size++; cout direct[index].ufd[i].filename == cur_opentable->uof[j].filename) { cout direct[index].ufd[i].filename, index); } //把最后一个文件的位置放到删除的位置 cur_user.next->direct[index].cur_file_size = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].cur_file_size; //注意这里 需要减一,由于本身结构的限制 cur_user.next->direct[index].directname = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].directname; //改变文件的位置 for (int i = 0; i direct[cur_user.next->cur_user_direct_size - 1].cur_file_size; i++) //注意这里的减一 { cur_user.next->direct[index].ufd[i].addr = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].addr; cur_user.next->direct[index].ufd[i].filename = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].filename; cur_user.next->direct[index].ufd[i].length = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].length; cur_user.next->direct[index].ufd[i].protect_code = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].protect_code; } cur_user.next->cur_user_direct_size--; //目录数量减1 cout direct[index].directname) { break; } } if (path == "") { cout direct[index].ufd[i].addr].next; while (temp != -1)//删除该文件的内存空间 { fat[temp].used = 0; temp = fat[temp].next; } cout direct[index].ufd[cur_user.next->direct[index].cur_file_size - 1].addr].used = 0; cur_user.next->direct[index].ufd[cur_user.next->direct[index].cur_file_size - 1].addr = cur_user.next->direct[index].ufd[i].addr; cur_user.next->direct[index].ufd[i].length = cur_user.next->direct[index].ufd[cur_user.next->direct[index].cur_file_size - 1].length; cur_user.next->direct[index].ufd[i].protect_code = cur_user.next->direct[index].ufd[cur_user.next->direct[index].cur_file_size - 1].protect_code; cur_user.next->direct[index].cur_file_size--; //将该文件设置为占用 fat[cur_user.next->direct[index].ufd[i].addr].used = 1; //next为-1 说明没有下一页,此为最后一页 int temp = fat[cur_user.next->direct[index].ufd[i].addr].next; while (temp != -1)//删除该文件的内存空间 { fat[temp].used = 0; temp = fat[temp].next; } cout direct[index].cur_file_size) { cout uof[cur_opentable->cur_openfilesize].filename = AllName;//在打开的文件数组中加入该文件 cur_opentable->uof[cur_opentable->cur_openfilesize].protect_code = cur_user.next->direct[index].ufd[k].protect_code;//保护码 cur_opentable->uof[cur_opentable->cur_openfilesize].pointer = cur_user.next->direct[index].ufd[k].length; cur_opentable->uof[cur_opentable->cur_openfilesize].addr = cur_user.next->direct[index].ufd[k].addr;//起始地址 cur_opentable->cur_openfilesize++; //文件打开数量加1 cout = cur_opentable->cur_openfilesize) { cout uof[cur_opentable->cur_openfilesize - 1].filename; cur_opentable->uof[i].pointer = cur_opentable->uof[cur_opentable->cur_openfilesize - 1].pointer; cur_opentable->uof[i].protect_code = cur_opentable->uof[cur_opentable->cur_openfilesize - 1].protect_code; cur_opentable->uof[i].addr = cur_opentable->uof[cur_opentable->cur_openfilesize - 1].addr; cur_opentable->cur_openfilesize--; cout direct[index].directname)//在当前用户的文件夹中找到相应的文件 { break; } } int i; //判读文件是否打开 for (i = 0; i cur_openfilesize; i++) { if (cur_opentable->uof[i].filename == path + '/' + name)//循环打开的文件 break; } if (i >= cur_opentable->cur_openfilesize) { cout uof[fd].pointer == 0) last_block_res = BLOCK_SIZE; else if(cur_opentable->uof[fd].pointer % BLOCK_SIZE == 0) last_block_res = 0; else last_block_res = BLOCK_SIZE - (cur_opentable->uof[fd].pointer % BLOCK_SIZE); //首先填满最后一个磁盘块 if(last_block_res) { if(last_block_res direct[index].ufd[temp].length = cur_user.next->direct[index].ufd[temp].length + cin_len; //更新用户目录文件表 cout cur_openfilesize) { cout = cur_user.next->cur_user_direct_size) { cout cur_user_direct_size) { cout cur_user_direct_size].directname = name; cur_user.next->direct[cur_user.next->cur_user_direct_size].cur_file_size = 0; //新创建的目录里面的文件个数为0 cur_user.next->cur_user_direct_size++; cout direct[index].ufd[i].filename == cur_opentable->uof[j].filename) { cout direct[index].ufd[i].filename, index); } //把最后一个文件的位置放到删除的位置 cur_user.next->direct[index].cur_file_size = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].cur_file_size; //注意这里 需要减一,由于本身结构的限制 cur_user.next->direct[index].directname = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].directname; //改变文件的位置 for (int i = 0; i direct[cur_user.next->cur_user_direct_size - 1].cur_file_size; i++) //注意这里的减一 { cur_user.next->direct[index].ufd[i].addr = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].addr; cur_user.next->direct[index].ufd[i].filename = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].filename; cur_user.next->direct[index].ufd[i].length = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].length; cur_user.next->direct[index].ufd[i].protect_code = cur_user.next->direct[cur_user.next->cur_user_direct_size - 1].ufd[i].protect_code; } cur_user.next->cur_user_direct_size--; //目录数量减1 cout direct[index].directname) { break; } } if (path == "") { cout name; cin >> protextcode; SET(name, protextcode); } else if (operaton == "rmdir") { string name; cin >> name; RMDIR(name); } else if (operaton == "look") { LOOK(); } else if (operaton == "fatused") { fatused(); } else { cout cur_user_direct_size; cur_user_size++; cur_opentable = &openfile[cur_user_size]; //指针指向文件打开表对象 cur_opentable->cur_openfilesize = 0; cout
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]