操作系统课程设计报告
专业:
班级:
姓名:
学号:
老师:
简单文件系统的实现
1
一、课程设计的目的
1. 通过具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部数据结构、功能以及实现过程的理解。 二、 课程设计要求
1. 在内存中开辟一个虚拟磁盘空间作为文件存储分区,在其上实现一个简单的基于多级目录的单用户单任务系统中的文件系统。在退出该文件系统的使用时,应将该虚拟文件系统以一个Windows 文件的方式保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘空间中。 2文件存储空间的分配可采用显式链接分配或其他的办法。
3空闲磁盘空间的管理可选择位示图或其他的办法。如果采用位示图来管理文件存储空间,并采用显式链接分配方式,那么可以将位示图合并到FAT中。
文件目录结构采用多级目录结构。为了简单起见,可以不使用索引结点,其中的每个目录项应包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护。 要求提供以下有关的操作命令:
my_format:对文件存储器进行格式化,即按照文件系统的结构对虚拟磁盘空间进行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构。 my_mkdir:用于创建子目录。 my_rmdir:用于删除子目录。 my_ls:用于显示目录中的内容。 my_cd:用于更改当前目录。 my_create:用于创建文件。 my_open:用于打开文件。 my_close:用于关闭文件。 my_write:用于写文件。 my_read:用于读文件。 my_rm:用于删除文件。
my_exitsys:用于退出文件系统。 三、程序的设计细想和框图 1.打开文件函数fopen()
(1)格式:FILE *fopen(const char *filename,const char *mode) (2)功能:按照指定打开方式打开指定文件。 (3)输入参数说明:
filename:待打开的文件名,如果不存在就创建该文件。 mode: 文件打开方式,常用的有:
\:为读而打开文本文件(不存在则出错)。
\:为写而打开文本文件(若不存在则创建该文件;反之,则从文件起始位置写,原内容将被覆盖)。
\:为在文件末尾添加数据而打开文本文件。(若不存在则创建该文件;反之,在原文件末尾追加)。
\:为读和写而打开文本文件。(读时,从头开始;在写数据时,新数据只覆盖所占的空间,其后不变) 。
\:首先建立一个新文件,进行写操作,随后可以从头开始读。(若文件存在,原内容将全部消失) 。
\:功能与\相同;只是在文件末尾添加新的数据后,可以从头开始读。
另外,上述模式字符串中都可以加一个“b”字符,如rb、wb、ab、rb+、wb+、ab+等组合,
2
字符“b”表示fopen() 函数打开的文件为二进制文件,而非纯文字文件。 (4)输出:一个指向FILE类型的指针。 2.关闭文件函数fclose()
(1)格式:int fclose(FILE * stream); (2)功能:用来关闭先前fopen()打开的一个文件。此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。 (3)输入参数说明:
stream:指向要关闭文件的指针,它是先前执行fopen()函数的返回值。
(4)输出:若关闭文件成功则返回0;有错误发生时则返回EOF并把错误代码存到errno。 3.读文件函数fread()
(1)格式:size_t fread( void *buffer, size_t size, size_t count, FILE *stream ); (2)功能:读二进制文件到内存。 (3)输入参数说明:
buffer:用于存放输入数据的缓冲区的首地址;
stream:使用fopen()打开的文件的指针,用于指示要读取的文件; size: 每个数据块的字节数; count: 要读入的数据块的个数; size*count:表示要求读取的字节数。 (4)输出:实际读取的数据块的个数。 4.写文件函数fwrite()
(1)格式:size_t fwite(const void *buffer,size_t size,size_t count,FILE *stream); (2)功能:将数据写到二进制文件中。 (3)输入参数说明:
buffer:用于存放输出数据的缓冲区的首地址;
stream:使用fopen()打开的文件的指针,用于指示要写出的文件; size: 每个数据块的字节数; count: 要写出的数据块的个数; size*count:表示要求写出的字符数。 (4)输出:实际写出的数据块的个数。 5.判断文件结束函数feof ()
(1)格式:int feof(FILE * stream)
(2)功能:用来判断是否已读取到文件末尾。 (3)输入参数说明:
stream:使用fopen()打开的文件的指针,用于指示要判断的文件。 (4)输出:如果已读到文件尾则返回非零值,其他情况返回0。 6 主要函数功能实现:
int format(); atherBlockNum = -1;ype=GENERAL; } } };
struct dirFile/*-------------目录文件结构---------------*/ {
struct FCB fcb[BlockFcbCount];
3
void init(int _FatherBlockNum,int _CurrentBlockNum,char *name)name,name); atherBlockNum=_FatherBlockNum;
fcb[0].currentBlockNum=_CurrentBlockNum;
fcb[0].type=DIRECTORY; atherBlockNum=_CurrentBlockNum; ype=Zero; ype==DIRECTORY && strcmp(dir->fcb[i].fname,sonfname)==0 ){ printf(\该文件夹下已经有同名的文件夹存在了!\\n\ return 0; } }
for(i = 1;i < BlockFcbCount; i++){ype==Zero) break; }
if(i == BlockFcbCount){
printf(\该目录已满!请选择新的目录下创建!\\n\ return 0; }
temp = i;
for(i = 3;i < BlockCount;i++) { if(osPoint->FAT1[i] == 0) break; }
if(i == BlockCount){
printf(\磁盘已满!\\n\ return 0; }
iFAT=i;
/*-------------接下来进行分配----------*/
osPoint->FAT1[iFAT]=osPoint->FAT2[iFAT] = 2; name,sonfname); dir->fcb[temp].type=DIRECTORY;
dir->fcb[temp].fatherBlockNum=current; dir->fcb[temp].currentBlockNum=iFAT;
ype==DIRECTORY && strcmp(dir->fcb[i].fname,sonfname)==0){ break; } }
temp=i;
if(i==BlockFcbCount){
printf(\当前目录下不存在该子目录!\\n\ return 0;
4
}
j = dir->fcb[temp].currentBlockNum; struct dirFile *sonDir; ype!=Zero) {
printf(\该文件夹为非空文件夹,为确保安全,请清空后再删除!\\n\ return 0; } }
/*开始删除子目录操作*/
osPoint->FAT1[j] = osPoint->FAT2[j]=0; nitialize(); ype == Zero && isFound == 0) { emptyNum = i; isFound = 1; }
else if(dir->fcb[i].type==GENERAL && strcmp(dir->fcb[i].fname,name)==0 ){ printf(\无法在同一目录下创建同名文件!\\n\ return 0; } }
if(emptyNum == 0){
printf(\已经达到目录项容纳上限,无法创建新目录!\\n\ return 0; }
for(i = 3;i
dir->fcb[emptyNum].fatherBlockNum=current; dir->fcb[emptyNum].currentBlockNum=iFAT; dir->fcb[emptyNum].size =0;
char* p = osPoint->data[iFAT -3]; memset(p,4,BlockSize);
printf(\在当前目录下创建文本文件成功!\\n\ return 1; }
/*-------查询子目录------------*/ int listshow() {
int i,DirCount=0,FileCount=0;
ype==GENERAL){ n\ }
if(dir->fcb[i].type==DIRECTORY){ n\
5