首页 > 其他分享 >操作系统实验 4 文件系统设计

操作系统实验 4 文件系统设计

时间:2024-11-26 16:30:02浏览次数:6  
标签:return 操作系统 currentDir int 文件系统 char fcb 实验 printf

一、 实验目的

通过一个简单文件系统的设计,加深理解文件系统的内部功能及内部实现。

二、 主要仪器设备、试剂或材料

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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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 &currentDir = *(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

相关文章

  • 计算机组成原理实验五 节拍发生器
    一、实验目的和要求了解CPU时序系统的工作原理;掌握层次化的方法;掌握节拍发生器的工作原理和构成。二、实验内容设计一个3位二进制同步计数器和一个3线~8线译码器,当计数器在连续时钟脉冲作用下,其输出通过译码后在实验板的8个指示灯依次显示出来。三、主要仪器......
  • 【操作系统】2.3_11_ 哲学家进餐问题
    https://www.bilibili.com/video/BV1YE411D7nH?spm_id_from=333.788.videopod.episodes&vd_source=6c2daed6731190bb7d70296d6b9746bb&p=36方法1n个哲学家,n个筷子创建一个初值为n-1的信号量,保证最多只有n-1个进程并发争抢资源,必有1个筷子资源余留,可以1个进程拿到两支筷子,不......
  • AS-V1000视频平台:部署在国产操作系统麒麟上并实现实时视频监控的浏览查看和回看
    目录一.问题来源二.银河麒麟系统的介绍三.下载麒麟系统的步骤四.配置平台并查看结果4.1外部设备接入4.1.1摄像机配置4.1.2平台配置4.2配置资源组4.3配置角色和用户4.4查看最终结果一.问题来源        客户想要在安装银河麒麟服务的服务器上使用AS-V1000......
  • 完成b/s实验
    <%@PageTitle="图书查询"Language="C#"MasterPageFile="~/Home/Home.Master"AutoEventWireup="true"CodeBehind="Index.aspx.cs"Inherits="Library.Home.Book.Index"%><asp:ContentID="Cont......
  • 完成c/s实验
    <?xmlversion="1.0"encoding="utf-8"?><root><!--MicrosoftResXSchemaVersion2.0TheprimarygoalsofthisformatistoallowasimpleXMLformatthatismostlyhumanreadable.Thegene......
  • 完成flash实验
    <!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>物理演示Flash动画按顺序显示</......
  • flask毕设大学实验中心教学管理系统的设计马实现(论文+程序)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容选题背景随着信息技术的飞速发展,高校教学管理的信息化已成为提升教育质量和管理效率的重要手段。大学实验中心作为教学和科研的重要基地,其管理系统......
  • 【Linux探索学习】第十六弹——进程地址空间:深入解析操作系统中的进程地址空间
    Linux学习笔记:https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482前言:进程地址空间是操作系统进程管理的重要概念之一,它定义了进程在执行时所能访问的内存布局。理解进程地址空间不仅有助于掌握操作系统的运行原理,也为程序优化、内存管......
  • 20222403 2024-2025-1 《网络与系统攻防技术》实验五实验报告
    1.实验内容(1)从www.besti.edu.cn、baidu.com、sina.com.cn中选择一个DNS域名进行查询,获取如下信息:DNS注册人及联系方式该域名对应IP地址IP地址注册人及联系方式IP地址所在国家、城市和具体地理位置PS:使用whois、dig、nslookup、traceroute、以及各类在线和离线工具进行搜集......
  • springboot毕设 实验室管理 程序+论文
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在高等教育与科研活动中,实验室作为理论与实践结合的重要场所,其管理效率与服务质量直接影响到教学与科研的质量与进度。随着信息技术的飞速发展,传统的......