长沙律师网站建设,沈阳公司做网站的,wordpress 取消自豪,建设网站代理商实验六 磁盘文件管理的模拟实现 实验目的
文件系统是操作系统中用来存储和管理信息的机构#xff0c;具有按名存取的功能#xff0c;不仅能方便用户对信息的使用#xff0c;也有效提高了信息的安全性。本实验模拟文件系统的目录结构#xff0c;并在此基础上实现文件的各种…实验六 磁盘文件管理的模拟实现 实验目的
文件系统是操作系统中用来存储和管理信息的机构具有按名存取的功能不仅能方便用户对信息的使用也有效提高了信息的安全性。本实验模拟文件系统的目录结构并在此基础上实现文件的各种操作方法。
通过本实验深入理解文件和目录的作用和功能熟悉与文件有关的系统调用从而更好地掌握文件系统功能。 实验内容
编程模拟实现磁盘文件管理。采用单级目录结构存放用户的所有文件系统提供创建文件、打开文件、读文件、写文件、关闭文件、删除文件命令。
1文件存储空间的分配采用位示图进行管理该部分内容请参考实验5。磁盘信息如下
现有一个磁盘组共有8个柱面。每个柱面有4个磁道每个磁道又划分成4个物理盘块假设1个磁盘块大小为128B。磁盘的空间使用情况用位示图表示。位示图用若干个字构成每一位对应一个磁盘块。“1”表示占用“0”表示空闲。假定字长为16位一个字可用来模拟磁盘的一个柱面。位示图的初始状态为第1个字为“1”其他全部空闲。
2文件目录采用单级目录结构。整个文件系统中只建立一张文件目录表UFD每个文件占一个目录项目录项中含文件名、文件保护方式、文件长度等属性。 文件名 文件保护方式 文件当前长度 文件最大长度 文件所在地址
图1 用户文件目录表UFD
文件所在地址存放文件分配的磁盘块号。
文件保护方式1表示文件可读2表示文件可写3表示文件可读写执行。
3系统建立一张用户打开文件表UOF用以记录系统当前正在使用的文件。假定最多允许打开4个文件该表应设置4项。当打开文件个数超过4个时应给出错误信息。用户打开文件表UOF的结构如下图所示。 图2 用户打开文件表UOF
图2中:
“文件操作方式”是指文件打开后要执行的操作
“状态”指用户打开文件表的各个表项为空表目或被占用。
读写指针用来指出对文件的存取位置。初始状态下读指针1写指针文件长度追加写。
4该文件系统提供6条命令创建、打开、读、写、关闭、删除。各命令说明如下。
创建一个文件当用户要在磁盘上建立一个文件时首先使用create命令向系统提出创建文件的请求
fd create(文件名文件最大字节长度文件保护方式);
例如
fd create(myfile12002);
由文件最大长度计算出文件应占用的磁盘块数然后为文件分配空间并登记在用户文件目录表UFD中同时登记在UOF表中。
不成功返回-1 成功返回文件描述符即在UOF表中的序号。 写文件命令 (文件描述符或文件名)
write(文件描述符或文件名要写的字节个数);
例如
write(myfile1,100); 模拟100个字节信息写入文件中。
不成功返回-1成功返回写入的字节个数 打开文件命令
fd open(文件描述符或文件名操作方式);
例如fdopena.txt;
不成功返回-1 成功返回文件描述符即在UOF表中的序号。 读文件命令(选做)
read(文件描述符或文件名要读的字节个数);
不成功返回-1 成功返回读取的字节个数 关闭文件命令
close(文件描述符或文件名);
不成功返回-1 成功返回0 删除文件命令
delete(文件名);
不成功返回-1 成功返回0 三. 测试用例
【1】创建文件记录各个数据结构情况
以下将创建6个文件且包含3种文件保护方式文件大小不完全相同。
1创建文件f1文件大小 5文件保护方式 3。 2创建文件f2文件大小 5文件保护方式 3。 3创建文件f3文件大小 10文件保护方式 3。 4创建文件f4文件大小 5文件保护方式 1。 5创建文件f5文件大小 5文件保护方式 3。 6创建文件f6文件大小 5文件保护方式 2。 上述文件创建完毕后磁盘位示图和文件列表的情况如下图所示。 UOF为空状态显示情况如下图所示。 【2】读写文件记录各个数据结构情况
在此步骤中应该先打开文件再对文件进行读/写操作最后关闭文件。如果直接读/写文件程序会提示相应报错。打开文件的操作序列如下所示。
1打开文件f1文件操作方式 3。 2打开文件f2文件操作方式 3。 3打开文件f3文件操作方式 3。 4打开文件f4文件操作方式 1。 5打开文件f5文件操作方式 3。 由5可知当打开文件数量大于4时程序会提示打开文件数目超过上限因此符合本实验中的【假定最多允许打开4个文件该表应设置4项。当打开文件个数超过4个时应给出错误信息】的要求。
此时UOF的情况如下图所示。 6读取文件f1读取字节数 3。 此时UOF的情况如下图所示。可以发现f1文件的读指针有所修改。 7读取文件f2读取字节数 10。 由7可知当从当前文件读指针开始经过输入的读取字节数后如果超过了文件的当前长度程序会提示读取文件长度超过上限。
8写入文件f3写入字节数 10。 此时UOF的情况如下图所示。可以发现f3文件的写指针、文件当前大小有所修改。 此时磁盘位示图的情况如下图所示。 9写入文件f4写入字节数 5。 由9可知如果当前文件的保护方式与操作方式存在不兼容的情况程序会提示该文件不能操作写。
10关闭文件f4。 11关闭文件f3。 此时UOF的情况如下图所示。可以发现f3文件和f4文件的信息已经不存在于UOF中说明关闭操作成功。 此时磁盘位示图的情况如下图所示。可以发现文件依然存在于磁盘中因此关闭操作并不会导致文件被删除的情况发生。 12关闭f2文件。 此时UOF的情况如下图所示。可以发现f2文件的信息已经不存在于UOF中说明关闭操作成功。 13关闭f1文件。 此时UOF的情况如下图所示。可以发现f1文件的信息已经不存在于UOF中说明关闭操作成功。 当前UOF为空说明没有文件处于打开状态。
【3】删除文件记录各个数据结构情况
1删除f2文件。 此时磁盘位示图的情况如下图所示。可以发现f2文件的信息已经不存在于磁盘位示图中说明删除操作成功。 2删除f3文件。 此时磁盘位示图的情况如下图所示。可以发现f3文件的信息已经不存在于磁盘位示图中说明删除操作成功。 3删除f4文件。 此时磁盘位示图的情况如下图所示。可以发现f4文件的信息已经不存在于磁盘位示图中说明删除操作成功。 后面将随机删除磁盘中剩余的各个文件此处不再进行赘述。
【4】所有的文件都删除掉时磁盘恢复为初始化状态 四. 实验分析和总结
【1】数据结构说明
1FCB的数据结构
FCB的代码实现如下图所示。 在本实验中利用struct构造FileInfo结构体实现对文件基本信息的记录即文件控制块。
该数据结构的基本变量包括文件名字的字符串file_name、文件大小的整型单变量file_size、文件分配扇区的一维数组allocated_sectors、文件保护方式的整型单变量protection。
2UOF的数据结构
UOF的代码实现如下图所示。 在本实验中利用struct构造UOF结构体实现对处于打开状态的各个文件进行记录即用户文件打开表。
该数据结构的基本变量包括文件名字的字符串file_name、文件操作方式的整型单变量protection、文件当前大小的整型单变量file_size、文件读指针的整型单变量read、文件写指针的整型单变量write、文件状态的整型单变量state在本次实验中并没有实际用到。
3磁盘空间的数据结构
磁盘空间的代码实现如下图所示。 在本实验中利用struct构造StorageManager结构体实现磁盘空间的初始化和管理以及链接相应的文件信息。
该数据结构的基本变量包括可用扇区总数的整型单变量available_sectors、磁盘位示图的二维数组bitmap、文件映射的哈希表files、打开文件映射的哈希表user。
该数据结构的功能包括构造磁盘空间函数createFile、创建文件函数createFile、显示磁盘存储状态函数displayStatus、显示磁盘中的文件序列函数fileDetails、删除文件函数deleteFile、打开文件函数openFile、关闭文件函数closeFile、写入文件函数writeFile、读取文件函数readFile、显示UOF状态函数displayUOF。
【2】程序流程图
1主函数的程序流程图 2构造磁盘空间函数的程序流程图 3创建文件函数的程序流程图 4显示磁盘存储状态函数的程序流程图 5显示磁盘中的文件序列函数的程序流程图 6删除文件函数的程序流程图 7打开文件函数的程序流程图第一、二个判断框右侧为否下测为是画错 8关闭文件函数的程序流程图 9写入文件函数的程序流程图 10读取文件函数的程序流程图 11显示UOF函数的程序流程图 【3】程序运行结果打印程序运行时的初值和运行结果
程序在测试用例下的运行结果如【三、测试用例】处所示。测试用例的流程图如下图所示。 【4】实验知识点总结实验收获与体会
1单级文件目录是最简单的文件目录只适用于单用户环境。在单级目录中利用用户提供的文件名用顺序查找法直接从文件目录中找到指名文件的目录项。 其优点是简单易实现实现了“按名存取”。 其缺点是1查找速度慢。在目录文件中查找文件目录项需要时间长。②不允许重名。同一个目录中的文件不允许同名。③不便于实现文件共享。
2两级目录结构由【主文件目录MFD】和【用户子目录UFD】组成。 其优点是①文件重名问题。每个用户可以使用相同的文件名。②提高了检索目录的速度。查找时间只是该用户所拥有的文件数目的一半时间而不是所有文件的一半时间。③文件共享允许不同用户使用不同文件名来访问同一个文件。原则上只要把对应的目录项指向同一物理位置的文件即可。 其缺点是用户不能对自己的文件进行分类管理。 查找文件的逻辑结构如下图所示。 3访问一个文件过程根据文件名对目录进行查询找出该文件的FCB或索引结点
根据FCB中的盘块号换算出物理地址最后把文件读进来。
4在文件保护方式中一共有3种状态。其中1表示文件可读2表示文件可写3表示文件可读写执行。
5在本次实验中深入了解了文件系统的工作原理和如何模拟文件的创建、写入、打开、读取、关闭和删除等操作。同时遇到了许多可能导致操作失败的情况如磁盘空间不足、文件不存在、文件打开数超限等因此学会了如何在程序中进行错误处理和返回适当的错误代码。
6实验要求模拟文件系统因此更加了解了系统调用的重要性。系统调用是用户程序与操作系统之间的桥梁它允许用户程序与系统资源进行交互。同时通过模拟用户打开文件表学会了如何在系统中管理多个同时打开的文件深入理解了多任务操作系统中的文件管理。
【5】实验源代码 #include iostream #include vector #include unordered_map using namespace std; const int MAXOPEN 4; const int MAXBYTE 50; // FCB or one-UFD struct FileInfo { string file_name; // 文件名字 int file_size; // 文件大小 vectorint allocated_sectors; // 文件分配的扇区 int protection; // 文件保护方式 }; // UOF struct UOF { string file_name; //文件名字 int protection; //文件操作方式 int file_size; //文件大小 当前 int read; //文件读指针 int write; //文件写指针 int state; //文件状态 //int file_path; //文件地址 不如直接看磁盘。 }; // Disk struct StorageManager { int available_sectors; // 可用扇区总数 vectorvectorint bitmap; // 磁盘位图 unordered_mapstring, FileInfo files; // 文件映射 unordered_mapstring, UOF user; // 打开文件映射 StorageManager(); // 构造函数yes bool createFile(const string, int, int); // 创建文件yes void displayStatus(); // 显示存储状态yes void fileDetails(const FileInfo); // 显示文件详情yes bool deleteFile(const string); // 删除文件yes bool openFile(const string, int); // 打开文件文件名操作方式yes bool closeFile(const string); // 关闭文件文件名yes bool writeFile(const string, int); // 写入文件文件名写入字节数yes bool readFile(const string, int); // 读取文件文件名读取字节数 yes void displayUOF(); // 显示UOF }; // show UOF void StorageManager::displayUOF(){ cout文件打开表UOFendl; for(const auto pair:user){ coutpair.first文件; cout[文件操作方式]pair.second.protection\t; cout[文件当前大小]pair.second.file_size\t; cout[文件读指针]pair.second.read\t; cout[文件写指针]pair.second.write\t; cout[文件状态]pair.second.state; coutendl; } } // 读取文件 bool StorageManager::readFile(const string name, int byte){ auto it user.find(name); if(it user.end()){ cout读取文件错误UOF里没有这个文件。endl; return false; } UOF temp it-second; if(temp.protection ! 3 and temp.protection ! 1){ cout读取文件错误该文件不能操作读。endl; return false; } if(temp.read byte temp.file_size){ cout读取文件错误读取文件长度超过上限。endl; return false; } // allow reading it-second.read byte; return true; } // 写入文件 bool StorageManager::writeFile(const string name, int byte){ auto it user.find(name); if(it user.end()){ cout写入文件错误UOF里没有这个文件。endl; return false; } UOF temp it-second; if(temp.protection ! 3 and temp.protection ! 2){ cout写入文件错误该文件不能操作写。endl; return false; } if(temp.write byte MAXBYTE){ cout写入文件错误写入文件长度超过上限。endl; return false; } // check disk if(available_sectors byte){ cout写入文件错误磁盘空间不足。endl; return false; } auto find files.find(name); FileInfo add find-second; int addbyte byte; // modify bitmap for(int i0;ibitmap.size()addbyte0;i){ for(int j0;jbitmap[i].size()addbyte0;j){ if(bitmap[i][j]0){ bitmap[i][j]1; find-second.allocated_sectors.push_back(i*16j); //allocated_sectors --addbyte; --available_sectors; } } } // allow writing it-second.write byte; // 修改写指针 it-second.file_size byte; // 修改当前文件长度 // update FCB find-second.file_size byte; fileDetails(find-second); return true; } // 关闭文件函数 bool StorageManager::closeFile(const string name){ auto it user.find(name); if(it user.end()){ cout关闭文件错误UOF里没有这个文件。endl; return false; } user.erase(it); return true; } // 打开文件函数 bool StorageManager::openFile(const string name, int opt){ auto it files.find(name); if(it files.end()){ cout打开文件错误没有这个文件。endl; return false; } FileInfo temp it-second; if(temp.protection 1){ if(opt ! 1){ cout打开文件错误文件保护方式有限制。endl; return false; } } else if(temp.protection 2){ if(opt ! 2){ cout打开文件错误文件保护方式有限制。endl; return false; } } auto newit user.find(name); if(newit ! user.end()){ cout打开文件错误这个文件已经打开。endl; return false; } if(user.size() MAXOPEN){ cout打开文件错误打开文件数目超过上限。endl; return false; } // 文件名字、操作、当前大小、读ptr、写ptr、状态 UOF t{name, opt, temp.file_size, 1, temp.file_size, 0}; user[name] t; //hash setting return true; } // 构造函数 8个柱面。每个柱面有4个磁道每个磁道又划分成4个物理盘块。 StorageManager::StorageManager() : available_sectors(128) { bitmap.resize(8, vectorint(16, 0)); // 构造8*16个空盘块 for (int j 0; j 16; j) { bitmap[0][j] 1; // 预留第一行作为系统文件该柱面不可用 } } // 创建文件函数 bool StorageManager::createFile(const string name, int size, int protection) { if (files.find(name) ! files.end()) { // 如果文件名字不在末尾则冲突 cout 创建文件错误: 文件已存在。 endl; return false; } if (size available_sectors) { // 如果文件大小大于空闲扇区大小 cout 创建文件错误: 磁盘空间不足。 endl; return false; } // 创建新文件的FCB FileInfo newFile{ name, size, {} , protection}; // 更新位示图中信息 for (int i 0; i bitmap.size() size 0; i) { for (int j 0; j bitmap[i].size() size 0; j) { if (bitmap[i][j] 0) { // 如果这个盘块为空 bitmap[i][j] 1; // 设置为已经分配 newFile.allocated_sectors.push_back(i * 16 j); // 分配区增加这个盘块 --size; // 空闲区大小-1 --available_sectors; // 同上 } } } files[name] newFile; // hash表设置 fileDetails(newFile); // 显示新建文件详情 return true; } // 显示磁盘分配情况函数 void StorageManager::displayStatus() { cout 磁盘位图 endl; for (int i 0; i bitmap.size(); i) { for (int j 0; j bitmap[i].size(); j) { cout bitmap[i][j] ; } cout endl; // 换行显示 } cout endl 文件列表: endl; for (const auto pair : files) { cout 文件 pair.first 的大小: pair.second.file_size endl; fileDetails(pair.second); } cout endl; } // 显示文件内存详情函数 void StorageManager::fileDetails(const FileInfo file) { cout 文件 file.file_name 的详细信息 endl; for (int sector : file.allocated_sectors) { cout 扇区: sector ; //遍历扇区 } cout endl; } // 删除文件函数 bool StorageManager::deleteFile(const string name) { auto it files.find(name); if (it files.end()) { cout 删除文件错误: 文件不存在。 endl; return false; } for (int sector : it-second.allocated_sectors) { int i sector / 16; int j sector % 16; bitmap[i][j] 0; available_sectors; } files.erase(it); auto another user.find(name); if (another ! user.end()){ user.erase(another); } cout 文件 name 已删除。 endl; return true; } // 菜单函数 void menu(StorageManager manager){ cout 根据数字提示选择操作: endl; cout 0:退出系统1:创建文件, 2:删除文件 endl; cout 4:打开文件5:读取文件, 6:写入文件, 7:关闭文件 endl; cout 3:磁盘位示图8用户文件打开表endl; } // 主函数 int main() { StorageManager manager; int action; string filename; int filesize; int protection; int byte; while (true) { bool flag 1; cout endl; menu(manager); cin action; cout endl; switch (action) { // 1创建文件 case 1: cout 输入文件名: ; cin filename; while (1){ cout 输入文件大小: ; cin filesize; if(filesize0){ cout文件大小必须为正请重新输入endl; } else{ break; } } while (1) { cout 输入文件保护方式; cin protection; if(protection 1 or protection 2 or protection 3){ break; } else{ cout文件保护方式输入错误请重新输入endl; } } if (manager.createFile(filename, filesize, protection)) { cout 文件创建成功。endl; } break; //2删除文件 case 2: cout 输入要删除的文件名: ; cin filename; if (manager.deleteFile(filename)) { cout 文件删除成功。endl; } break; //3磁盘位示图 case 3: manager.displayStatus(); break; //4:打开文件 case 4: cout 输入要打开的文件名: ; cin filename; while(1){ cout请输入文件操作方式; cin protection; if(protection ! 1 and protection ! 2 and protection ! 3){ cout文件操作方式错误请输入1、2、3中的其中一个。endl; } else { break; } } if (manager.openFile(filename,protection)) { cout 文件打开成功。endl; } break; //5:读取文件 case 5: cout输入要读取的文件名; cinfilename; while(1){ cout输入要读取的字节数; cinbyte; if(byte 0){ cout读取字节大小必须为正请重新输入endl; } else{ break; } } if(manager.readFile(filename, byte)){ cout文件读取成功。endl; } break; //6:写入文件 case 6: cout输入要写入的文件名; cinfilename; while(1){ cout输入要写入的字节数; cinbyte; if(byte 0){ cout写入字节大小必须为正请重新输入endl; } else{ break; } } if(manager.writeFile(filename, byte)){ cout文件写入成功。endl; } break; //7:关闭文件 case 7: cout 输入要关闭的文件名: ; cin filename; if(manager.closeFile(filename)){ cout 文件关闭成功。endl; } break; //8:UOF case 8: manager.displayUOF(); break; case 0: cout 程序退出感谢使用。endl; flag 0; break; default: cout 无效的数字操作请重新输入。endl; break; } if(!flag){ break; } } return 0; } 五实验指导
1. 主要的数据结构供参考
UFD、UOF表可采用结构数组也可采用链表方式下面是结构数组方式的定义。
#define OPEN_FILE_MAX 4
#define FILE_NAME_MAX 20
#define FILE_MAX 10 //系统中可创建的文件数量最大值
#define FILE_BLOCK_MAX 10 //文件磁盘块最大值 struct FCB{ // 文件控制块 int file_descriptor; // 文件标识符 char file_name[FILE_NAME_MAX]; // 文件名 int protected_mode; // 1:可读2:可写3:可读写执行 int file_current_length; // 文件当前长度字节 int file_max_length; // 文件最大长度字节 // 以下是文件存储空间分配时产生的值不需要用户定义 int length; // 文件的块数 int block[FILE_BLOCK_MAX]; // 存放文件的具体盘块号 …….
} UFD_table[FILE_MAX]; // UFD表信息文件目录结构 struct UOF{ char file_name[FILE_NAME_MAX]; int operate_mode; // 打开后要执行的操作 1只读 2读写 3读写执行 int read_pointer; // 初始状态下为1 int write_pointer; // 初始状态下为文件长度 int file_current_length; int file_path; int state;
} UOF_table[OPEN_FILE_MAX]; // 用户打开文件表 2. 文件系统执行流程
实验中应先建立用户文件目录和用户打开文件表然后给出一个菜单请求用户选择要执行的操作。
1文件系统执行流程如下图所示。 2创建文件命令和流程图
fd create(文件名文件最大字节长度文件保护方式) 3写文件命令及其流程图
write(文件描述符或文件名要写的字节个数); 4打开文件命令及其流程图
fd open(文件描述符或文件名操作方式); 5读文件命令及其流程图
read(文件描述符或文件名要读的字节个数); 6关闭文件命令及其流程图
close(文件描述符或文件名);