模拟文件系统的设计与实现之欧阳地创编
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中北大学
操作系统课程设计
说明书
学院、系:软件学院专业:软件工程
学生姓名:xxx
学
号:xxx
设计题目:模拟文件系统的设计与实现
起迄日期: 2015年12月28日- 2016年1月8日
指导教师:xxx
2016 年1月8日
1需求分析
通过模拟文件系统的实现,深入理解操作系统中文件系统的理论知识, 加深对教材中的重要算法的理解。
同时通过编程实现这些算法,更好地掌握操作系统的原理及实现方法,提高综合运用各专业课知识的能力;掌握操
作系统结构、实现机理和各种典型算法,系统地了解操作系统的设计和实现思路,并了解操作系统的发展动向和趋势。
模拟二级文件管理系统的课程设计目的是通过研究Linux 的文件系统结构,模拟设计一个简单的二级文件系统,第一级为主目录文件,第二级为用户文件。
2
总体设计
结合数据结构、程序设计、计算机原理等课程的知识,设计一个二级文件系统,进一步理解操作系统。
文件的创建: create 文件关闭:close 文件的打开:open
文件的读:read 文件的写:write 文件关闭:close
删除文件:delete 创建子目录:mkdir 删除子目录:rmdir
列出文件目录:dir 退出:exit
系统执行流程图
#define DISKSIZE 1024 //磁盘块的大小1K
#define DISK_NUM 1024 //磁盘块数目1K
#define FATSIZE DISK_NUM*sizeof(struct fatitem) //FAT表大小
#define ROOT_DISK_NO FATSIZE/DISKSIZE+1
//根目录起始盘块号
#define ROOT_DISK_SIZE sizeof(struct direct) //根目录大小
#define DIR_MAXSIZE 1024 //路径最大长度为1KB
#define MSD 5 //最大子目录数5
#define MOFN 5 //最大文件深度为5
#define MAX_WRITE 1024*128 //最大写入文字长度128KB
struct fatitem /* size 8*/
{
int item; /*存放文件下一个磁盘的指针*/
char em_disk; /*磁盘块是否空闲标志位 0 空闲*/
};
struct direct
{
/*-----文件控制快信息-----*/
struct FCB
{
char name[9]; /*文件/目录名 8位*/
char property; /*属性 1位目录 0位普通文件*/
int size; /*文件/目录字节数、盘块数)*/
int firstdisk; /*文件/目录起始盘块号*/
int next; /*子目录起始盘块号*/
int sign; /*1是根目录 0不是根目录*/ }directitem[MSD+2];
};
struct opentable
{
struct openttableitem
{
char name[9]; /*文件名*/
int firstdisk; /*起始盘块号*/
int size; /*文件的大小*/
}openitem[MOFN];
int cur_size; /*当前打文件的数目*/
};
管理文件的主要代码:
int create(char *name)
{
int i,j;
if(strlen(name)>8) /*文件名大于 8位*/
return(-1);
for(j=2;j<MSD+2;j++) /*检查创建文件是否与已存在的文件重名*/
{
if(!strcmp(cur_dir-
>directitem[j].name,name))
break;
}
if(j<MSD+2) /*文件已经存在*/
return(-4);
for(i=2;i<MSD+2;i++) /*找到第一个空闲子目录*/ {
if(cur_dir->directitem[i].firstdisk==-1)
break;
}
if(i>=MSD+2) /*无空目录项*/
return(-2);
if(u_opentable.cur_size>=MOFN) /*打开文件太多*/
return(-3);
for(j=ROOT_DISK_NO+1;j<DISK_NUM;j++) /*找到空闲盘块 j 后退出*/
{
if(fat[j].em_disk=='0')
break;
}
if(j>=DISK_NUM)
return(-5);
fat[j].em_disk = '1'; /*将空闲块置为已经分配*/
/*-----------填写目录项-----------------*/
strcpy(cur_dir->directitem[i].name,name);
cur_dir->directitem[i].firstdisk = j;
cur_dir->directitem[i].size = 0;
cur_dir->directitem[i].next = j;
cur_dir->directitem[i].property = '0';
/*---------------------------------*/
fd = open(name);
return 0;
}
int open(char *name)
{
int i, j;
for(i=2;i<MSD+2;i++) /*文件是否存在*/
{
if(!strcmp(cur_dir-
>directitem[i].name,name))
break;
}
if(i>=MSD+2)
return(-1);
/*--------是文件还是目录-----------------------*/
if(cur_dir->directitem[i].property=='1')
return(-4);
/*--------文件是否打开-----------------------*/
for(j=0;j<MOFN;j++)
{
if(!strcmp(u_opentable.openitem[j].name,name))
break;
}
if(j<MOFN) /*文件已经打开*/
return(-2);
if(u_opentable.cur_size>=MOFN) /*文件打开太多*/
return(-3);
/*--------查找一个空闲用户打开表项-----------------------*/
for(j=0;j<MOFN;j++)
{
if(u_opentable.openitem[j].firstdisk==-1)
break;
}
/*--------------填写表项的相关信息------------------------*/
u_opentable.openitem[j].firstdisk = cur_dir->directitem[i].firstdisk;
strcpy(u_opentable.openitem[j].name,name);
u_opentable.openitem[j].size = cur_dir->directitem[i].size;
u_opentable.cur_size++;
/*----------返回用户打开表表项的序号--------------------------*/
return(j);
}
int close(char *name)
{
int i;
for(i=0;i<MOFN;i++)
{
if(!strcmp(u_opentable.openitem[i].name,name))
break;
}
if(i>=MOFN)
return(-1);
/*-----------清空该文件的用户打开表项的内容---------------------*/
strcpy(u_opentable.openitem[i].name,"");
u_opentable.openitem[i].firstdisk = -1;
u_opentable.openitem[i].size = 0;
u_opentable.cur_size--;
return 0;
}
int write(int fd, char *buf, int len)
{
char *first;
int item, i, j, k;
int ilen1, ilen2, modlen, temp;
/*----------用 $ 字符作为空格 # 字符作为换行符-----------------------*/
char Space = 32;
char Endter= '\n';
for(i=0;i<len;i++)
{
if(buf[i] == '$')
buf[i] = Space;
else if(buf[i] == '#')
buf[i] = Endter;
}
/*----------读取用户打开表对应表项第一个盘块号-----------------------*/
item = u_opentable.openitem[fd].firstdisk;
/*-------------找到当前目录所对应表项的序号-------------------------*/
for(i=2;i<MSD+2;i++)
{
if(cur_dir-
>directitem[i].firstdisk==item)
break;
}
temp = i; /*-存放当前目录项的下标-*/
/*------找到的item 是该文件的最后一块磁盘块-------------------*/
while(fat[item].item!=-1)
{
item =fat[item].item; /*-查找该文件的下一盘块--*/
}
/*-----计算出该文件的最末地址-------*/
first = fdisk+item*DISKSIZE+u_opentable.openitem[fd].size %DISKSIZE;
/*-----如果最后磁盘块剩余的大小大于要写入的文件的大小-------*/
if(DISKSIZE-
u_opentable.openitem[fd].size%DISKSIZE>len) {
strcpy(first,buf);
u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len;
cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len;
}
else
{
for(i=0;i<(DISKSIZE-
u_opentable.openitem[fd].size%DISKSIZE);i++)
{/*写一部分内容到最后一块磁盘块的剩余空间(字节)*/
first[i] = buf [i];
}
/*-----计算分配完最后一块磁盘的剩余空间(字节) 还剩下多少字节未存储-------*/
ilen1 = len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);
ilen2 = ilen1/DISKSIZE;
modlen = ilen1%DISKSIZE;
if(modlen>0)
ilen2 = ilen2+1; /*--还需要多少块磁盘块-*/
for(j=0;j<ilen2;j++)
{
for(i=ROOT_DISK_NO+1;i<DISK_NUM;i++)/*寻找空闲磁盘块*/
{
if(fat[i].em_disk=='0')
break;
}
if(i>=DISK_NUM) /*--如果磁盘块已经分配完了-*/
return(-1);
first = fdisk+i*DISKSIZE; /*--找到的那块空闲磁盘块的起始地址-*/
if(j==ilen2-1) /*--如果是最后要分配的一块-*/
{
for(k=0;k<len-(DISKSIZE-
u_opentable.openitem[fd].size%DISKSIZE)-
j*DISKSIZE;k++)
first[k] = buf[k];
}
else/*-如果不是要最后分配的一块--*/
{
for(k=0;k<DISKSIZE;k++)
first[k] =buf[k];
}
fat[item].item = i; /*--找到一块后将它的序号存放在上一块的指针中-*/
fat[i].em_disk = '1'; /*--置找到的磁盘快的空闲标志位为已分配-*/
fat[i].item = -1; /*--它的指针为 -1 (即没有下一块)-*/
}
/*--修改长度-*/
u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len;
cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len;
}
return 0;
}
int read(int fd, char *buf)
{
int len = u_opentable.openitem[fd].size;
char *first;
int i, j, item;
int ilen1, modlen;
item = u_opentable.openitem[fd].firstdisk;
ilen1 = len/DISKSIZE;
modlen = len%DISKSIZE;
if(modlen!=0)
ilen1 = ilen1+1; /*--计算文件所占磁盘的块数-*/
first = fdisk+item*DISKSIZE; /*--计算文件的起始位置-*/
for(i=0;i<ilen1;i++)
{
if(i==ilen1-1) /*--如果在最后一个磁盘块-*/
{
for(j=0;j<len-i*DISKSIZE;j++)
buf[i*DISKSIZE+j] = first[j];
}
else /*--不在最后一块磁盘块-*/
{
for(j=0;j<len-i*DISKSIZE;j++)
buf[i*DISKSIZE+j] = first[j];
item = fat[item].item; /*-查找下一盘块-*/
first = fdisk+item*DISKSIZE;
}
}
return 0;
}
int del(char *name)
{
int i,cur_item,item,temp;
for(i=2;i<MSD+2;i++) /*--查找要删除文件是否在当前目录中-*/
{
if(!strcmp(cur_dir-
>directitem[i].name,name))
break;
}
cur_item = i; /*--用来保存目录项的序号,供释放目录中-*/
if(i>=MSD+2) /*--如果不在当前目录中-*/
return(-1);
if(cur_dir-
>directitem[cur_item].property!='0') /*--如果删除的(不)是目录-*/
return(-3);
for(i=0;i<MOFN;i++) /*--如果文件打开,则不能删除,退出-*/
{
if(!strcmp(u_opentable.openitem[i].name,name))
return(-2);
}
item = cur_dir->directitem[cur_item].firstdisk;/*--该文件的起始盘块号-*/
while(item!=-1) /*--释放空间,将FAT表对应项进行修改-*/
{
temp = fat[item].item;
fat[item].item = -1;
fat[item].em_disk = '0';
item = temp;
}
/*-----------------释放目录项-----------------------*/
cur_dir->directitem[cur_item].sign = 0;
cur_dir->directitem[cur_item].firstdisk = -1;
strcpy(u_opentable.openitem[cur_item].name,"" );
cur_dir->directitem[cur_item].next = -1;
cur_dir->directitem[cur_item].property = '0';
cur_dir->directitem[cur_item].size = 0;
return 0;
}
主函数:
int main()
{
FILE *fp;
char ch;
char a[100];
char code[11][10];
char name[10];
int i,flag,r_size;
char *contect;
contect = (char *)malloc(MAX_WRITE*sizeof(char));
if((fp=fopen("disk.dat","rb"))==NULL)
{
printf("You have not format,Do you want format?(y/n)");
scanf("%c",&ch);
if(ch=='y')
{
initfile();
printf("Successfully format! \n");
}
else
{
return 0;
}
}
enter();
print();
show();
strcpy(code[0],"exit");
strcpy(code[1],"create");
strcpy(code[2],"open");
strcpy(code[3],"close");
strcpy(code[4],"write");
strcpy(code[5],"read");
strcpy(code[6],"del");
strcpy(code[7],"mkdir");
strcpy(code[8],"rmdir");
strcpy(code[9],"dir");
strcpy(code[10],"cd");
while(1)
{
scanf("%s",a);
for(i=0;i<11;i++)
{
if(!strcmp(code[i],a))
break;
}
switch(i)
{
case 0: //退出文件系统
free(contect);
halt();
return 0;
case 1: //创建文件
scanf("%s",name);
flag = create(name);
if(flag==-1)
{
printf("Error: \n The length is too long !\n");
}
else if(flag==-2)
{
printf("Error: \n The direct item is already full !\n");
}
else if(flag==-3)
{
printf("Error: \n The number of openfile is too much !\n");
}
else if(flag==-4)
{
printf("Error: \n The name is already in the direct !\n");
}
else if(flag==-5)
{
printf("Error: \n The disk space is full!\n");
}
else
{
printf("Successfully create a file! \n");
}
show();
break;
case 2://打开文件
scanf("%s",name);
fd = open(name);
if(fd == -1)
{
printf("Error: \n The open
file not exit! \n");
}
else if(fd == -2)
{
printf("Error: \n The file have already opened! \n");
}
else if(fd == -3)
{
printf("Error: \n The number of open file is too much! \n");
}
else if(fd == -4)
{
printf("Error: \n It is a direct,can not open for read or write! \n");
}
else
{
printf("Successfully opened! \n");
}
show();
break;
case 3://关闭文件
scanf("%s",name);
flag = close(name);
if(flag == -1)
{
printf("Error:\n The file is not opened ! \n");
}
else
{
printf("Successfully closed! \n");
}
show();
break;
case 4://写文件
if(fd ==-1)
{
printf("Error:\n The file is not opened ! \n");
}
else
{
printf("Please input the file contect:");
scanf("%s",contect);
flag=write(fd,contect,strlen(contect));
if(flag == 0)
{
printf("Successfully
write! \n");
}
else
{
printf("Error:\n The disk size is not enough! \n");
}
}
show();
break;
case 5://读文件
if(fd ==-1)
{
printf("Error:\n The file is not opened ! \n");
}
else
{
flag = read(fd,contect);
if(flag == 0)
{
for(i=0;i<u_opentable.openitem[fd].size;i++)
{
printf("%c",contect[i]);
}
printf("\t\n");
}
}
show();
break;
case 6://删除文件
scanf("%s",name);
flag = del(name);
if(flag == -1)
{
printf("Error:\n The file not exit! \n");
}
else if(flag == -2)
{
printf("Error:\n The file is opened,please first close it ! \n");
}
else if(flag == -3)
{
printf("Error:\n The delete is not file ! \n");
}
else
{
printf("Successfully delete! \n");
}
show();
break;
}
}
}
程序运行截图:
4.心得体会
在设计的过程中,我查询了不少相关资料,不断地发现问题、提出问题、解决问题。
用C做程序开发语言,让我重新认识了C的基础,在新语言不断出现并发展迅速的今天,重新体会到C的基础性、重要性,以及面对过程,面对函数式的编程方式。
在对自己所编写的源程序段的纠错的过程中,使我更好的理解了操作系统中文件系统的理论知识,同时在编程时用到了模块化的设计思想,这种编程方法可以使我们的编程更简单,可以使我们的查错与纠错变得更加
方便。
总的来说通过这次的设计学习使我学到了很多在平时的学习中学不到的很多东西,对操作系统有了更深一层的了解,同时也提高了C语言的能力,由于时间以及个人知识的问题,因此有很多的地方还需要改进。
在以后的学习中还要更加努力。