一、 实验目的
通过一个简单文件系统的设计,加深理解文件系统的内部功能及内部实现。
二、 主要仪器设备、试剂或材料
VMware虚拟机
三、 实验内容
为 Linux 系统设计一个简单的二级文件系统。要求做到以下几点:
(1)可以实现下列几条命令。
mkdir 创建目录
rmdir 删除目录
cd 进入目录
ls 显示目录、文件
create 创建文件
rm 删除文件
open 打开文件
close 关闭文件
write 写文件
read 读文件
(2)列目录时要列出文件名、文件类型、拥有者、创建时间等信息。
四、 实验思路及结果分析
1. 新建目录
创建filesystemlab并打开
mkdir -p filesystemlab/root && cd filesystemlab
2. 将 test.cpp 放入 filesystemlab 目录
3. 编译
g++ test.cpp -o test
4. 运行
./test
5. 实验演示截图
完整代码(完整代码也可在本文绑定资源中获得):
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <iostream>
#include <time.h>
using namespace std;
#define GENERAL 1
#define DIRECTORY 2
#define Zero 0
//1:普通文件;2:目录文件;0:空文件
/************************************************************************/
/* FCB存储 */
/************************************************************************/
struct FCB
{
char fname[16]; //文件名
char type; // 0:空文件 1:普通文件 2:目录文件
int size; //文件大小
int fatherBlockNum; //当前的父目录盘块号
int currentBlockNum; //当前的盘块
char Dir_Time[25];//文件夹时间
char File_Time[25];//文件时间
void initialize() //清空函数
{
strcpy(fname,"\0");
type = Zero;
size =0;
fatherBlockNum = currentBlockNum = 0;
}
};
/************************************************************************/
/* 文件系统初始化参数设定 */
/************************************************************************/
const char* FilePath = "../filesystemlab/root/file";//初始文件目录
const int BlockSize = 512; //盘块大小
const int OPEN_MAX = 5; //能打开最多的文件数
const int BlockCount = 128; //盘块数
const int DiskSize = BlockSize * BlockCount; //磁盘大小
const int BlockFcbCount = BlockSize/sizeof(FCB);//目录文件的最多FCB数
int OpenFileCount = 0; // 统计当前打开文件数目
struct OPENLIST //用户文件打开表
{
int files; //当前打开文件数
FCB f[OPEN_MAX]; //FCB拷贝
OPENLIST()
{
files=0;
for(int i=0;i<OPEN_MAX;i++){
f[i].fatherBlockNum = -1;//为分配打开
f[i].type=GENERAL;
}
}
};
/************************************************************************/
/* 目录文件结构 */
/************************************************************************/
struct dirFile
{
struct FCB fcb[BlockFcbCount];
void init(int _FatherBlockNum,int _CurrentBlockNum,char *name)
//父块号,当前块号,目录名
{
strcpy(fcb[0].fname,name); //本身的FCB
fcb[0].fatherBlockNum=_FatherBlockNum;
fcb[0].currentBlockNum=_CurrentBlockNum;
fcb[0].type=DIRECTORY; //标记目录文件
for(int i=1;i<BlockFcbCount;i++){
fcb[i].fatherBlockNum=_CurrentBlockNum; //标记为子项
fcb[i].type=Zero; // 标记为空白项
}
}
};
/************************************************************************/
/* 根目录初始化设置 */
/************************************************************************/
struct DISK
{
int FAT1[BlockCount]; //FAT1
int FAT2[BlockCount]; //FAT2
struct dirFile root; //根目录
char data[BlockCount-3][BlockSize];
void format(){
memset(FAT1,0,BlockCount); //FAT1
memset(FAT2,0,BlockCount); //FAT2
FAT1[0]=FAT1[1]=FAT1[2]=-2; //0,1,2盘块号依次代表FAT1,FAT2,根目录区
FAT2[0]=FAT2[1]=FAT2[2]=-2; //FAT作备份
root.init(2,2,(char *)"../filesystemlab/root/");//根目录区
memset(data,0,sizeof(data));//数据区
}
};
FILE *fp; //磁盘文件地址
char * BaseAddr; //虚拟磁盘空间基地址
string currentPath="../filesystemlab/root/file/"; //当前路径
int current=2; //当前目录的盘块号
string cmd; //输入指令
struct DISK *osPoint; //磁盘操作系统指针
char command[16]; //文件名标识
struct OPENLIST* openlist; //用户文件列表指针
/************************************************************************/
/* 指令集函数 */
/************************************************************************/
int format();
int mkdir(char *sonfname);
int rmdir(char *sonfname);
int create(char *name);
int listshow();
int destroy(char *name);
int changePath(char *sonfname);
int write(char *name);
int exit();
int open(char *file);
int close(char *file);
int read(char *file);
/************************************************************************/
/* 文件系统初始化/格式化实现 */
/************************************************************************/
int format()
{
// 初始化FAT表和根目录
osPoint->format();
current = 2; // 根目录
currentPath = "../filesystemlab/root/file/";
printf("磁盘已格式化,系统已重置\n");
return 1;
}
/************************************************************************/
/* 创建文件夹实现 */
/************************************************************************/
int mkdir(char *sonfname)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type != Zero && strcmp(currentDir.fcb[i].fname, sonfname) == 0)
{
printf("目录名已存在\n");
return -1;
}
}
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == Zero)
{
int newBlock = -1;
for (int j = 3; j < BlockCount; ++j)
{
if (osPoint->FAT1[j] == 0)
{
newBlock = j;
break;
}
}
if (newBlock == -1)
{
printf("磁盘空间不足\n");
return -1;
}
osPoint->FAT1[newBlock] = -1;
osPoint->FAT2[newBlock] = -1;
currentDir.fcb[i].type = DIRECTORY;
strcpy(currentDir.fcb[i].fname, sonfname);
currentDir.fcb[i].fatherBlockNum = current;
currentDir.fcb[i].currentBlockNum = newBlock;
dirFile &newDir = *(dirFile *)&osPoint->data[newBlock - 3];
newDir.init(current, newBlock, sonfname);
printf("目录创建成功\n");
return 1;
}
}
printf("当前目录已满\n");
return -1;
}
/************************************************************************/
/* 删除文件夹实现 */
/************************************************************************/
int rmdir(char *sonfname)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == DIRECTORY && strcmp(currentDir.fcb[i].fname, sonfname) == 0)
{
int blockNum = currentDir.fcb[i].currentBlockNum;
dirFile &subDir = *(dirFile *)&osPoint->data[blockNum - 3];
for (int j = 0; j < BlockFcbCount; ++j)
{
if (subDir.fcb[j].type != Zero)
{
printf("目录不为空,无法删除\n");
return -1;
}
}
osPoint->FAT1[blockNum] = 0;
osPoint->FAT2[blockNum] = 0;
currentDir.fcb[i].initialize();
printf("目录删除成功\n");
return 1;
}
}
printf("目录不存在\n");
return -1;
}
/************************************************************************/
/* 创建文件实现 */
/************************************************************************/
int create(char *name)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type != Zero && strcmp(currentDir.fcb[i].fname, name) == 0)
{
printf("文件名已存在\n");
return -1;
}
}
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == Zero)
{
int newBlock = -1;
for (int j = 3; j < BlockCount; ++j)
{
if (osPoint->FAT1[j] == 0)
{
newBlock = j;
break;
}
}
if (newBlock == -1)
{
printf("磁盘空间不足\n");
return -1;
}
osPoint->FAT1[newBlock] = -1;
osPoint->FAT2[newBlock] = -1;
currentDir.fcb[i].type = GENERAL;
strcpy(currentDir.fcb[i].fname, name);
currentDir.fcb[i].fatherBlockNum = current;
currentDir.fcb[i].currentBlockNum = newBlock;
printf("文件创建成功\n");
return 1;
}
}
printf("当前目录已满\n");
return -1;
}
/************************************************************************/
/* 列出文件/目录实现 */
/************************************************************************/
int listshow()
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
printf("当前目录内容:\n");
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type != Zero)
{
printf("%s\t%s\n", currentDir.fcb[i].fname, currentDir.fcb[i].type == DIRECTORY ? "目录" : "文件");
}
}
return 1;
}
/************************************************************************/
/* 删除文件实现 */
/************************************************************************/
int destroy(char *name)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == GENERAL && strcmp(currentDir.fcb[i].fname, name) == 0)
{
int blockNum = currentDir.fcb[i].currentBlockNum;
osPoint->FAT1[blockNum] = 0;
osPoint->FAT2[blockNum] = 0;
currentDir.fcb[i].initialize();
printf("文件删除成功\n");
return 1;
}
}
printf("文件不存在\n");
return -1;
}
/************************************************************************/
/* 切换目录实现 */
/************************************************************************/
int changePath(char *sonfname)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
if (strcmp(sonfname, "..") == 0)
{
if (current == 2)
{
printf("已经是根目录\n");
return -1;
}
current = currentDir.fcb[0].fatherBlockNum;
currentPath = currentPath.substr(0, currentPath.find_last_of('/', currentPath.length() - 2)) + "/";
return 1;
}
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == DIRECTORY && strcmp(currentDir.fcb[i].fname, sonfname) == 0)
{
current = currentDir.fcb[i].currentBlockNum;
currentPath += sonfname;
currentPath += "/";
return 1;
}
}
printf("目录不存在\n");
return -1;
}
/************************************************************************/
/* 系统退出实现 */
/************************************************************************/
int exit()
{
if ((fp = fopen(FilePath, "w")) != NULL)
{
fwrite(BaseAddr, sizeof(char), DiskSize, fp);
fclose(fp);
printf("磁盘已保存\n");
}
else
{
printf("磁盘保存失败\n");
}
free(BaseAddr);
delete openlist;
return 1;
}
/************************************************************************/
/* 写文件 */
/************************************************************************/
int write(char *name)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == GENERAL && strcmp(currentDir.fcb[i].fname, name) == 0)
{
int blockNum = currentDir.fcb[i].currentBlockNum;
if (blockNum < 3 || blockNum >= BlockCount)
{
printf("文件块号无效\n");
return -1;
}
printf("请输入写入内容(以单独一行'EOF'结束):\n");
string input, data;
while (getline(cin, input) && input != "EOF")
{
data += input + "\n";
}
if (data.size() > BlockSize)
{
printf("内容过大,无法写入\n");
return -1;
}
memcpy(osPoint->data[blockNum - 3], data.c_str(), data.size());
currentDir.fcb[i].size = data.size();
printf("写入成功\n");
return 1;
}
}
printf("文件不存在\n");
return -1;
}
/************************************************************************/
/* 读取文件 */
/************************************************************************/
int read(char *file)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == GENERAL && strcmp(currentDir.fcb[i].fname, file) == 0)
{
int blockNum = currentDir.fcb[i].currentBlockNum;
if (blockNum < 3 || blockNum >= BlockCount)
{
printf("文件块号无效\n");
return -1;
}
char buffer[BlockSize + 1] = {0};
memcpy(buffer, osPoint->data[blockNum - 3], currentDir.fcb[i].size);
printf("文件内容:\n%s\n", buffer);
return 1;
}
}
printf("文件不存在\n");
return -1;
}
/************************************************************************/
/* 打开文件 */
/************************************************************************/
int open(char *file)
{
dirFile ¤tDir = *(dirFile *)&osPoint->data[current - 3];
for (int i = 0; i < BlockFcbCount; ++i)
{
if (currentDir.fcb[i].type == GENERAL && strcmp(currentDir.fcb[i].fname, file) == 0)
{
if (OpenFileCount < OPEN_MAX)
{
openlist->f[OpenFileCount++] = currentDir.fcb[i];
printf("文件打开成功\n");
return 1;
}
printf("打开文件数已达上限\n");
return -1;
}
}
printf("文件不存在\n");
return -1;
}
/************************************************************************/
/* 关闭文件 */
/************************************************************************/
int close(char *file)
{
for (int i = 0; i < OpenFileCount; ++i)
{
if (strcmp(openlist->f[i].fname, file) == 0)
{
openlist->f[i] = openlist->f[--OpenFileCount];
printf("文件关闭成功\n");
return 1;
}
}
printf("文件未打开\n");
return -1;
}
/************************************************************************/
/* 功能介绍说明 */
/************************************************************************/
void MenuShow()
{
printf(
"************************************************************************\n"
"* 操作指令集 *\n"
"* 文件夹_创建:mkdir <dirname> *\n"
"* 文件夹_删除:rmdir <dirname> *\n"
"* 文件夹_显示:ls <dirname> *\n"
"* 文件夹_更改:cd <dirname> *\n"
"* 文件_创建打开:create <filename> *\n"
"* 文件_选择写入:write <filename> *\n"
"* 文件_选择读取:read <filename> *\n"
"* 文件_选择打开:open <filename> *\n"
"* 文件_选择关闭:close <filename> *\n"
"* 文件_选择删除:rm <filename> *\n"
"* 系统_磁盘清空:format *\n"
"* 系统_清屏:clear *\n"
"* 系统_安全退出:exit *\n"
"* 系统_命令提示符:help *\n"
"************************************************************************\n");
}
/************************************************************************/
/* 退出目录 */
/************************************************************************/
void Menu_Exit()
{
time_t now;
now = time(NULL);
char NOW[25];
strcpy(NOW,ctime(&now));
NOW[24]='\0';
system("clear");
printf(
"************************************************************************\n"
"* 文件系统 *\n"
"************************************************************************\n"
"***********************%s************************\n"
"************************************************************************\n"
"* 欢迎使用本系统 *\n"
"* 下次再见 *\n"
"************************************************************************\n",NOW);
}
/************************************************************************/
/* 主函数 */
/************************************************************************/
int main()
{
MenuShow();
openlist=new OPENLIST;//创建用户文件打开表
BaseAddr=(char *)malloc(DiskSize);//申请虚拟空间并且初始化
osPoint=(struct DISK *)(BaseAddr);//虚拟磁盘初始化
if((fp=fopen(FilePath,"r"))!=NULL){//加载磁盘文件
fread(BaseAddr,sizeof(char),DiskSize,fp);
printf("\n磁盘已加载,您处于%s:\n\n",FilePath);
}
else{
printf("欢迎使用本文件管理系统!\t正在初始化...\n");
format();
printf("初始化已完成!现在请使用,祝您使用愉快:\n\n");
}
while(1)
{
cout<<currentPath;
cin>>cmd;
if(cmd=="format"){
format();
}
else if(cmd=="mkdir"){
cin>>command;
mkdir(command);
}
else if(cmd=="rmdir"){
cin>>command;
rmdir(command);
}
else if(cmd=="ls"){
listshow();
}
else if(cmd=="cd"){
cin>>command;
changePath(command);
}
else if(cmd=="create"){
cin>>command;
create(command);
}
else if(cmd=="write"){
cin>>command;
write(command);
}
else if(cmd=="read"){
cin>>command;
read(command);
}
else if(cmd=="rm"){
cin>>command;
destroy(command);
}
else if(cmd=="open"){
cin>>command;
open(command);
}
else if(cmd=="close"){
cin>>command;
close(command);
}
else if(cmd=="clear"){
system("clear");
}
else if(cmd=="help"){
MenuShow();
}
else if(cmd=="exit"){
exit();
break;
}
else
cout<<"指令无效,请重新输入:"<<endl;
}
Menu_Exit();
return 1;
}
标签:return,操作系统,currentDir,int,文件系统,char,fcb,实验,printf
From: https://blog.csdn.net/qianqianaao/article/details/144041918