操作系统 文件存储空间管理位示图法.docx
《操作系统 文件存储空间管理位示图法.docx》由会员分享,可在线阅读,更多相关《操作系统 文件存储空间管理位示图法.docx(39页珍藏版)》请在冰豆网上搜索。
![操作系统 文件存储空间管理位示图法.docx](https://file1.bdocx.com/fileroot1/2023-2/7/2f1c1d8c-132b-4f14-9ca0-ea8d4a6f7bd0/2f1c1d8c-132b-4f14-9ca0-ea8d4a6f7bd01.gif)
操作系统文件存储空间管理位示图法
#include
#include
#include
#include
usingnamespacestd;
structFCB
{
charfname[16];//文件名
inttype;//1代表普通文件2代表目录文件0表示空文件
intsize;//文件大小
intfatherBlockNum;//当前的父目录盘块号
intfirstBlockNum;//该文件第一个盘块号
intcurrentBlockNum;//当前的盘块
intlastBlockNum;
voidinitialize()
{
strcpy(fname,"\0");
type=0;
size=0;
fatherBlockNum=firstBlockNum=currentBlockNum=lastBlockNum=0;
}
};
/*常量设置*/
constchar*FilePath="C:
\\myfiles";
constintBlockSize=512;//盘块大小(可配置)
constintOPEN_MAX=5;//能打开最多的文件数
constintBlockCount=BlockSize/sizeof(int);//盘块数
constintDiskSize=BlockSize*BlockCount;//磁盘大小
constintBlockFcbCount=BlockSize/sizeof(FCB);//目录文件的最多FCB数
constintm=16;//位示图的列数
constintn=BlockCount/m;//位示图的行数
//constintIOBUF_SIZE=512;
//charIOBuffer[IOBUF_SIZE];
intOpenFileCount=0;
structOPENLIST//用户文件打开表
{
intfiles;//当前打开文件数
FCBf[OPEN_MAX];//FCB拷贝
OPENLIST()
{
files=0;
for(inti=0;if[i].fatherBlockNum=-1;//为分配打开
f[i].type=0;
}
}
};
/*-------------目录文件结构---------------*/
structdirFile
{
structFCBfcb[BlockFcbCount];
voidinit(int_FatherBlockNum,int_FirstBlockNum,int_CurrentBlockNum,int_LastBlockNum,char*name)//父块号,第一个盘块号,当前块号,目录名
{
strcpy(fcb[0].fname,name);//本身的FCB
fcb[0].fatherBlockNum=_FatherBlockNum;
fcb[0].firstBlockNum=_FirstBlockNum;
fcb[0].currentBlockNum=_CurrentBlockNum;
fcb[0].lastBlockNum=_LastBlockNum;
fcb[0].type=2;//标记目录文件
for(inti=1;i{
fcb[i].fatherBlockNum=_CurrentBlockNum;//标记为子项
fcb[i].type=0;//标记为空白项
}
}
};
/**********************************************************************/
structDISK
{
intFAT1[BlockCount];//FAT1
intFAT2[BlockCount];//FAT2
structdirFileroot;//根目录
intmap[n][m];//位示图,最初都为0
intcheck[n][m];//check数组用于一致性检查,作为数据计数器;
chardata[BlockCount-5][BlockSize];
voidformat()
{
memset(FAT1,0,BlockCount);//FAT1
memset(FAT2,0,BlockCount);//FAT2
FAT1[0]=FAT1[1]=FAT1[2]=FAT1[3]=FAT1[4]=-2;//0,1,2盘块号依次代表FAT1,FAT2,根目录区
FAT2[0]=FAT2[1]=FAT2[2]=FAT2[3]=FAT2[4]=-2;//FAT作备份
root.init(2,2,2,2,"G:
\\");//根目录区
for(inti=0;i<=BlockCount;i++)//map[0][0],map[0][1],map[0][1],map[0][2],map[0][3],map[0][4]以及check
{//对应位置为占用
if(i<5)
{
map[0][i]=0;
check[0][i]=1;
}
else
{map[i/16][i%16]=1;
check[i/16][i%16]=0;
}
}
memset(data,0,sizeof(data));//数据区
}
};
/*-----------------全局变量--------------------------*/
FILE*fp;//磁盘文件地址
char*BaseAddr;//虚拟磁盘空间基地址
stringcurrentPath="G:
\\";//当前路径
intcurrent=2;//当前目录的盘块号
stringcmd;//输入指令
structDISK*osPoint;//磁盘操作系统指针
charcommand[16];//文件名标识
structOPENLIST*openlist;//用户文件列表指针
/*-----------函数事先申明--------------------*/
intformat();
intmkdir(char*sonfname);
intrmdir(char*sonfname);
intcreate(char*name);
intlistshow();
intdelfile(char*name);
intchangePath(char*sonfname);
intwrite(char*name);
intexit();
intopen(char*file);
intclose(char*file);
intread(char*file);
/*------------初始化-----------------------*/
intformat()
{
current=2;
currentPath="G:
\\";//当前路径
osPoint->format();//打开文件列表初始化
deleteopenlist;
openlist=newOPENLIST;
/*-------保存到磁盘上myfiles--------*/
fp=fopen(FilePath,"w+");
fwrite(BaseAddr,sizeof(char),DiskSize,fp);
fclose(fp);
printf("----------------------------------------------------------\n\n");
return1;
}
/*-----------------------创建子目录-------------------*/
intmkdir(char*sonfname)
{
//判断是否有重名
//寻找空白子目录项
//寻找空白盘块号
//当前目录下增加该子目录项
//分配子目录盘块,并且初始化
//修改fat表
inti,temp,iFAT;
structdirFile*dir;//当前目录的指针
if(current==2)
dir=&(osPoint->root);
else
dir=(structdirFile*)(osPoint->data[current-5]);
/*--------为了避免该目录下同名文件夹--------*/
for(i=1;i{
if(dir->fcb[i].type==2&&strcmp(dir->fcb[i].fname,sonfname)==0)
{
printf("该文件夹下已经有同名的文件夹存在了!
\n");
return0;
}
}
//查找空白fcb序号
for(i=1;i{
if(dir->fcb[i].type==0)
break;
}
if(i==BlockFcbCount)
{
printf("该目录已满!
请选择新的目录下创建!
\n");
return0;
}
temp=i;
for(i=5;i{
if(osPoint->map[i/m][i%m]>0)
break;
}
if(i==BlockCount)
{
printf("磁盘已满!
\n");
return0;
}
iFAT=i;
/*-------------接下来进行分配----------*/
osPoint->map[iFAT/m][iFAT%m]--;//对应盘块在位示图置0;
osPoint->FAT1[iFAT]=osPoint->FAT2[iFAT]=iFAT;//每个目录文件只占一块所以在文件分配表中其链接的下一块为其本身
osPoint->check[iFAT/m][iFAT%m]++;//对应盘块在数据计数器中置1;
//填写该分派新的盘块的参数
strcpy(dir->fcb[temp].fname,sonfname);
dir->fcb[temp].type=2;
dir->fcb[temp].fatherBlockNum=current;
dir->fcb[temp].firstBlockNum=iFAT;
dir->fcb[temp].currentBlockNum=iFAT;
dir->fcb[temp].lastBlockNum=iFAT;
//初始化子目录文件盘块
dir=(structdirFile*)(osPoint->data[iFAT-5]);//定位到子目录盘块号
dir->init(current,iFAT,iFAT,iFAT,sonfname);//iFAT是要分配的块号,这里的current用来指要分配的块的父块号
printf("---------------------------------------------------------------\n\n");
return1;
}
/*-------删除当前目录下的文件夹--------*/
intrmdir(char*sonfname)
{
//if(子目录不存在)returnerror
//if(子目录不是空文件夹)returnerror
//回收子目录磁盘块号b(修改fat)
//回收子目录占据目录项
inti,temp,j;//确保当前目录下有该文件,并记录下该FCB下标
structdirFile*dir;//当前目录的指针
if(current==2)
dir=&(osPoint->root);
else
dir=(structdirFile*)(osPoint->data[current-5]);
for(i=1;i{//查找该目录文件
if(dir->fcb[i].type==2&&strcmp(dir->fcb[i].fname,sonfname)==0)
{
break;
}
}
temp=i;
if(i==BlockFcbCount)
{
printf("当前目录下不存在该子目录!
\n");
return0;
}
j=dir->fcb[temp].currentBlockNum;
structdirFile*sonDir;//当前子目录的指针
sonDir=(structdirFile*)(osPoint->data[j-5]);
for(i=1;i{
if(sonDir->fcb[i].type!
=0)
{
printf("该文件夹为非空文件夹,为确保安全,请清空后再删除!
\n");
return0;
}
}
/*开始删除子目录操作*/
osPoint->FAT1[j]=osPoint->FAT2[j]=0;//fat清空
osPoint->map[j/m][j%m]++;//位示图对应盘块置为空闲
osPoint->check[j/m][j%m]--;//数据计数器对应盘块置为空闲
char*p=osPoint->data[j-5];//格式化子目录
memset(p,0,BlockSize);
dir->fcb[temp].initialize();//回收子目录占据目录项
printf("---------------------------------------------------------------\n\n");
return1;
}
/*-----------在当前目录下创建文本文件---------------*/
intcreate(char*name)
{
inti,iFAT;//temp,
intemptyNum=0,isFound=0;//空闲目录项个数
structdirFile*dir;//当前目录的指针
if(current==2)
dir=&(osPoint->root);
else
dir=(structdirFile*)(osPoint->data[current-3]);
//查看目录是否已满
//为了避免同名的文本文件
for(i=1;i{
if(dir->fcb[i].type==0&&isFound==0)
{
emptyNum=i;
isFound=1;
}
elseif(dir->fcb[i].type==1&&strcmp(dir->fcb[i].fname,name)==0)
{
printf("无法在同一目录下创建同名文件!
\n");
return0;
}
}
if(emptyNum==0)
{
printf("已经达到目录项容纳上限,无法创建新文件!
\n");
return0;
}
//查找位示图寻找空白区,用来分配磁盘块号j
for(i=5;i{
if(osPoint->map[i/m][i%m]>0)
break;
}
if(i==BlockCount)
{
printf("磁盘已满!
\n");
return0;
}
iFAT=i;
/*------进入分配阶段---------*/
//位示图分配
osPoint->map[iFAT/m][iFAT%m]--;
//分配磁盘块
osPoint->FAT1[iFAT]=osPoint->FAT2[iFAT]=iFAT;//文件刚刚创建时只分配一块FAT连接自身
//数据计数器对应位置为占用
osPoint->check[iFAT/m][iFAT%m]++;
/*-----------接下来进行分配----------*/
//填写该分派新的盘块的参数
strcpy(dir->fcb[emptyNum].fname,name);
dir->fcb[emptyNum].type=1;
dir->fcb[emptyNum].fatherBlockNum=current;
dir->fcb[emptyNum].firstBlockNum=iFAT;
dir->fcb[emptyNum].currentBlockNum=iFAT;
dir->fcb[emptyNum].lastBlockNum=iFAT;
dir->fcb[emptyNum].size=0;
char*p=osPoint->data[iFAT-5];
memset(p,'#',BlockSize);
printf("----------------------------------------------------------------\n\n");
return1;
}
/*-------查询子目录------------*/
intlistshow()
{
inti,DirCount=0,FileCount=0;
//搜索当前目录
structdirFile*dir;//当前目录的指针
if(current==2)
dir=&(osPoint->root);
else
dir=(structdirFile*)(osPoint->data[current-5]);
for(i=1;i{
if(dir->fcb[i].type==1)
{//查找普通文件
FileCount++;
printf("%s文本文件.\n",dir->fcb[i].fname);
}
if(dir->fcb[i].type==2)
{//查找目录文件
DirCount++;
printf("%s文件夹.\n",dir->fcb[i].fname);
}
}
printf("\n该目录下共有%d个文本文件,%d个文件夹\n\n",FileCount,DirCount);
printf("--------------------------------------------------------\n\n");
return1;
}
/*---------在当前目录下删除文件-----------*/
intdelfile(char*name)
{
inti,temp,j;
//确保当前目录下有该文件,并且记录下它的FCB下标
structdirFile*dir;//当前目录的指针
if(current==2)
dir=&(osPoint->root);
else
dir=(structdirFile*)(osPoint->data[current-3]);
for(i=1;i{
if(dir->fcb[i].type==1&&strcmp(dir->fcb[i].fname,name)==0)
{
break;
}
}
if(i==BlockFcbCount)
{
printf("当前目录下不存在该文件!
\n");
return0;
}
//从打开列表中删除
close(name);
printf("文件已删除!
\n");
temp=i;
/*开始删除文件操作*/
dir->fcb[temp].currentBlockNum=dir->fcb[temp].firstBlockNum;
intnext=dir->fcb[temp].currentBlockNum;
//查找盘块号j
do
{
j=dir->fcb[temp].currentBlockNum=next;
next=osPoint->FAT1[j];
osPoint->FAT1[j]=osPoint->FAT2[j]=0;//fat1,fat2表标记为空白
osPoint->map[j/m][j%m]++;//位示图该盘块号对应位置为空闲
osPoint->check[j/m][j%m]--;//数据计数器对应盘块号置为空闲
char*p=osPoint->data[j-5];
memset(p,0,BlockSize);//清除原文本文件的内容
}
while(dir->fcb[temp].currentBlockNum!
=dir->fcb[temp].lastBlockNum);
dir->fcb[temp].initialize();//type=0;//标记该目录项为空文件
printf("------------------------------------------------------------\n\n");
return1;
}
/*--------------进入当前目录下的子目录--------------*/
intchangePath(char*sonfname)
{
structdirFile*dir;//当前目录的指针
if(current==2)
dir=&(osPoint->root);
else
dir=(structdirFile*)(osPoint->data[current-5]);
/*回到父目录*/
if(strcmp(sonfname,"..")==0)
{
if(current==2)
{
printf("你现已经在根目录下!
\n");