操作系统课程设计——文件管理模拟 C++版
参考博客:【操作系统之模拟文件管理系统 - CSDN App】
并在此基础上进行了修改和完善部分代码
这是我的第一篇CSDN,内容有点长
实验内容
文件管理
一、目的
通过模拟磁盘,完成操作系统的文件管理功能,掌握包括目录结构的管理、外存空【操作系统之模拟文件管理系统 - CSDN App】间的分配与释放以及空闲空间管理三部分。为写入模拟磁盘的数据文件建立目录,目录可以是单级文件目录、双级文件目录、树形结构目录。在目录中选择某个文件可以将其数据读入模拟内存。
二、设计内容
- 通过初始化操作建立一个模拟磁盘,在模拟磁盘中保存目录和文件内容。创建该模拟磁盘时可创建初始的根目录内容、文件分配表。
- 文件目录项(可以采用FCB格式)应包括文件名、类型(目录 or文件)、创建日期、大小、第一个磁盘块块号。
- 目录管理需支持:
新建目录:在目录中新建空目录; 删除目录:删除空目录
为文件建立目录项:一个文件创建成功后,为该文件创建目录项,并将文件和相关信息写入目录;
删除文件:删除目录中某个文件,删除其在磁盘中的数据,并删除目录项。如果被删除文件已经读入内存应阻止删除,完成基本的文件保护。
三、 设计要求
- 不同的功能使用不同的函数实现(模块化),对每个函数的功能和调用接口要注释清楚。对程序其它部分也进行必要的注释。
- 对系统进行功能模块分析、画出总流程图和各模块流程图。
- 用户界面要求使用方便、简洁明了、美观大方、格式统一。所有功能可以反复使用,最好使用菜单。
- 通过命令行相应选项能直接进入某个相应菜单选项的功能模块。
- 所有程序需调试通过。
实验说明
本实验是参考了http://t.csdnimg.cn/B0Fqh
,并在此基础上进行了修改和完善部分代码。
本次实验为Linux系统设计了一个简单的二级文件系统,可以做到以下几点:
- 可用命令及说明
- register 用户的注册
- login 用户的登入
- cd 切换目录
- mkdir 创建用户的子目录
- rmdir 删除用户的子目录
- dir 显示当前目录的子目录
- create 创建文件夹的文件
- del 删除文件夹的文件
- open 打开文件
- close 关闭文件
- read 读文件
- write 写文件
- set 设置文件的保护码
- exit 退出系统
- look 查看系统中的所有用户
- fatused 查看目前块的状态
- 用户登入时会对用户名和密码进行匹配
- 进入系统的第一步需要注册账号并登入(为测试方便,初始化了一个用户)
- 在创建子目录时必须先登入
- 不可在打开的状态下进行任何删除操作
- 删除子目录或文件时释放其空间
- 创建文件和打开文件时必须先进入文件夹
- 文件被打开后可进行读写操作
- 文件保护码为2可读可写,为0不可读,其他不可写
文件结构
这些图表是我的一点理解,可能存在偏差
用户文件结构
打开文件结构
创建文件流程图
删除文件流程图
代码说明
整体结构
#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
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。