操作系统课程设计之三
设计任务:模拟 OS 文件系统
在任一 OS(Window 或者 Dos;也可以是在 Linux 下,但要求能将结果演示给老
师看)下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的模拟 OS
文件系统。
1、在现有机器硬盘上开辟 10M(共 10000 个盘块,每盘块大小为 1k)的硬盘空间
(生成一个 10M 的用户文件 SDisk.dat 即可),作为设定的硬盘空间。
2、编写一管理程序 SDisk,对此空间进行管理,以模拟 OS 文件系统,要求:
⑴、盘块大小 1k
⑵、空闲盘块的管理:采用位示图法
⑶、文件空间管理:采用 FAT(文件分配表),每个盘块号占 2 个字节
⑷、目录项管理:
①、每个目录项占用 32 字节,其中前 8 个字节(0-7)为文件名,之后跟 3 个字节
(8-10)的扩展名,26-27 字节,存放文件的第一个盘块号,最后四个字节
(28-31),存放文件长度(如果目录项对应的是下一级子目录(文件),其文件
长度部分为 0)
②、目录按文件方式管理,每个目录仅用一个盘块(即 1k,最多装 32 个目录项)
③、第 0 个目录项为本目录,即“.”,第 0 个字节为“.”,即 0x2E,第 26-27 字
节指明本目录所在盘块。
④、第 1 个目录项为父目录,即“..”,第 0,1 个字节为“..”即 0x2E,0x2E,第
26-27 字节指明父目录所在盘块。
⑤、每个目录实际能放下文件或子目录 30 项。
⑸、文件系统空间分配:
①、第 0 个盘块(1k)存放磁盘信息(可以设定为格式说明“FAT32”、盘块大小,盘块数等
内容)
②、第 1 个盘块起,至 125 盘块,共 125 个盘块(125k)存放 FAT 内容
③、第 126、127(2 个)盘块,存放位示图
④、从第 128 盘块至 10000 盘块,皆为数据(区)盘块,其逻辑编号从 0 开始,至
9872 号数据盘块,即第 0 数据盘块为 128 号盘块,第 1 数据盘块为 129 号盘块,…
⑤、第 0 数据盘块(即 128 号盘块),存放根目录(同样只用一个盘块作根目录),
由于第 0、1 目录项为“.”(本目录), “..”(父目录),因此根目录下同
样只能存放 30 个文件或目录,并且从第 2 个目录项开始。
⑥、文件或子目录数据,放在第 1 数据盘块及以后的数据盘块中,由用户按需要使
用。
3、SDisk 管理程序的功能要求如下:
⑴、正常情况下,显示等待命令输入符号#
⑵、改变目录命令:
#cd 目录名,改变当前工作目录,目录不存在时给出出错信息
#cd ..,返回上一级目录,如果是根目录,给出提示信息
⑶、生成新目录
#md 目录名,创建新目录(需要更改 FAT 内容和位示图内容)
⑷、删除目录
#rd 目录名,删除目录,如果目录不存在时给出出错信息(需要更改 FAT 内容
和位示图内容)
⑸、显示目录
#dir,显示指定目录下或当前目录下的信息,包括文件名、扩展名、物理地址
(文件或目录第一个盘块号)、文件长度、子目录
⑹、创建新文件
#CreateFile 文件名.扩展名 文件长度,根据文件名.扩展名,创建一个目录项
(fcb),根据文件长度和位示图中空闲盘块情况,分配足够多的连续盘块,给新文
件(需要更改 FAT 内容和位示图内容)。
⑺、删除文件
#DelFile 文件名.扩展名,在文件所在的目录项中,将第一个字节变为 0xE5,
并同时修改 FAT 内容和位示图内容;如果文件不存在,给出出错信息
⑻、文件拷贝
#CopyFile 老文件,新文件,为新文件创建一个目录项,并将老文件内容复制到
新文件中,并同时修改 FAT 内容和位示图内容
⑼、显示位示图内容
#ShowBitMP,将位示图内容(已有信息部分),显示在屏幕上(按十六进制)
⑽、显示 FAT 内容
#ShowFAT,将 FAT 内容(已有信息部分),显示在屏幕上(按十六进制)
4、程序的总体流程为:
⑴、输出提示符#,等待接受命令,分析键入的命令;
⑵、对合法的命令,执行相应的处理程序,否则输出错误信息,继续等待新命令
(1、请参考“03.FAT32文件系统简介.doc”中,有关文件系统的规定;
2、请参考WinHex中,目录所显示的信息进行编程)
//关于 FAT 和 MAP 表的解释
//用 bitset 库,做 MAP 的是否判断,因为作业要求从数据块从 128 位开始,所以
bitset 的前 128 位被置为-1,同样 FAT 表也是,其次,MAP 表和 FAT 表同样是用数
组方式做保存,这样就略过了是对具体地址的操作,从数组的下标很容易的定位,
关于对 FAT 表和 MAP 表的用法
1. 当要用到数据块是,查询 MAP 表(因为只做比较查询即可),查询到的未用位置
置 1,然后在 FAT 表上进行相应记录,在本程序做出的规定是,当文件夹 FAT
表做-1,若是文件则按照 FAT 做对应的顺序记录,最后一块同样是-1 结束,
2. 回收的时候,是按照 FAT 表的首项,做顺序置 0,然后 MAP 也在相应位置置 0
#include
#include
#include
#include
#include
/***********************************************************/
//AUTHOR:CHENLOG
//ENVIROMENT:VC2008 WIN7
//DATE:2011-6-5 VERSION 1.0
/***********************************************************/
using namespace std;
const int BLOCKNUM_SIZE=2;
const int BLOCK_SIZE=1024;
const int BLOCK_NUM=10001;
const int DISK_SIZE=1024*1000*10;
const int LIST_SIZE=32;
const int MAP_SIZE=10001;
const int FATNUM=125;
const int FATLIST=512;
const int DATABEG=128;
//盘块号大小
//一个盘块大小数
//盘块数量
//磁盘大小
//目录项大小
//MAP 长度
//FAT的盘块数 第块没有用
//每个盘口FAT的记录数
//数据项开始FAT号
struct FCB
{
char fname[8];
char exname[3];
short fnum;
int length;
//文件名
//扩展名
//首块号
//文件大小, 目录则文件大小为;
};
struct fatid{
short id[FATNUM*FATLIST];
//FAT 大小512个记录 一块
//当前FAT号
//当前目录块号初始化是+1 由于第个单元没有使用
//磁盘的首地址
//window文件保存地址
//window 文件地址
//当前路径
//输入指令
}*FAT;
struct map{
bitset maplist;
}*MAP;
struct DIR
{
struct FCB list[LIST_SIZE+1];
}*filedir;
int currentid=128;
int currentdir=128;
char *file;
char *FilePath="myfat";
FILE *fp;
string CURRENT="root\\";
char cmd[30];
char command[16];
/*
*对文件存储器进行格式化
*创建根目录
*
*/
void findBit(struct map *MAP)
{
}
void init(struct fatid *FAT)
{
int i,j;
for(i=1;iDATABEG)
FAT->id[i]=0;
else
FAT->id[i]=-1;
}
}
void format()
{
bool i;
FAT=(struct fatid *)(file+BLOCK_SIZE);
//当前FAT地址
MAP=(struct map *)(file+(FATNUM+1)*BLOCK_SIZE);
init(FAT);
//初始化位示图
FAT->id[0]=9872;
filedir=(struct DIR *)(file+(FATNUM+1+2)*BLOCK_SIZE);
//当前目录指针地址
FAT->id[128]=-1;
FAT->id[0]=9872-1;
strcpy(filedir->list[0].fname,".");
strcpy(filedir->list[0].exname,"dir");
filedir->list[0].fnum=currentdir;
filedir->list[0].length=0;
strcpy(filedir->list[1].fname,"..");
strcpy(filedir->list[1].exname,"dir");
filedir->list[1].fnum=currentdir;
filedir->list[1].length=0;
fp=fopen(FilePath,"w+");
fwrite(file,sizeof(char),DISK_SIZE,fp);
fclose(fp);
printf("初始化已经完成,现在可以进行操作了!\n\n");
}
/*
*创建子目录
*/
int mkdir(char *str)
{
int i,j;
int blockid;
//将要创建的FAT号
int blockdir;
int listnum;
//将要创建的目录块号
//目录块内编号
//当前目录指针
struct fatid *flagid;
struct DIR *dir;
struct map *MAP;
struct fatid *FAT;
if(strcmp(str,"")==0)
{
printf("目录名称不能为空\n");
return 0;
}
dir=(struct DIR *)(file+(currentdir)*BLOCK_SIZE);
MAP=(struct map *)(file+(FATNUM+1)*BLOCK_SIZE);
FAT=(struct fatid *)(file+BLOCK_SIZE);
//从128块数据块 实际上的块开始搜索
for(i=DATABEG+1;imaplist[i]==0)
break;
}
if(i>BLOCK_NUM)
{
printf("内存不足\n");
return 0;
}
MAP->maplist[i]=1;
//map 置即已用
dir=(struct DIR *)(file+(currentdir)*BLOCK_SIZE);
for(i=2;ilist[i].fname,str)==0)
{
printf("目录下有同名文件夹\n");
return 0;
}
}
for(i=2;ilist[i].fname,"")==0)
//有空的目录块且无重名,第一版本的时候与上面
的循环放在一起,存在一个情况是前面的建立的目录删除后,直接被同名的覆盖了
break;
if(i>LIST_SIZE)
{
printf("内存不足\n");
return 0;
}
}
flagid=(struct fatid *)(file+BLOCK_SIZE); //fat 首位地址
for(j=DATABEG+1;jid[j]==0)
{
blockdir=j;
break;
}
}
strcpy(dir->list[i].fname,str);
dir->list[i].fnum=blockdir;
strcpy(dir->list[i].exname,"dir");
dir->list[i].length=0;
//为新目录项创建根目录
dir=(struct DIR *)(file+blockdir*BLOCK_SIZE);
strcpy(dir->list[0].fname,".");
strcpy(dir->list[0].exname,"dir");
dir->list[0].fnum=blockdir;
dir->list[0].length=0;
strcpy(dir->list[1].fname,"..");
strcpy(dir->list[1].exname,"dir");
dir->list[1].fnum=currentdir;
dir->list[1].length=0;
flagid->id[j]=-1;
FAT->id[0]=FAT->id[0]-1;
//修改FAT 目录尾部
printf("已经成功创建目录%s \n",str);
return 0;
}
/*
*显示目录
*/
int listshow()
{
int i,sumfile,sumdir,fl[100],dr[100];//fl 为文件的号数,dr为目录的号数
sumfile=sumdir=0;
struct DIR *dir;
struct fatid *FAT;
dir=(struct DIR *)(file+currentdir*BLOCK_SIZE);
for(i=0;ilist[i].length==0&&(strcmp(dir->list[i].fname,"")!=0)&&(dir->list[i].fnum!=0))