45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:实现虚拟文件系统的步骤

实现虚拟文件系统的步骤

2016-09-06 17:55:05 来源:www.45fan.com 【

实现虚拟文件系统的步骤

这个是我们操作系统课程设计的一个题目,当时参加完趋势竞赛后在连续熬了一个星期通宵后我又熬了一个通宵把这个写好了.时间比较紧,因为晚上还要赶着写报告,真是辛苦.这个程序也就当时写了三个多小时吧,难免有些漏洞.

// FileSys.cpp : Defines the entry point for the console application.
//
#include <stdafx.h>
#include <stdio.h>
#include <iostream.h>
#include <dos.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h> /* ctime, asctime */
#include <string.h>
#define FILE_BLOCKS 16 /*文件占用的最大块数*/
#define NAME_LENGTH 10
#define DEV_SIZE 1024 * 1024*100 /*虚拟磁盘拥有100M的空间*/
#define BLOCK_NUM 512*200 /*磁盘中存放数据的总逻辑块数*/
#define INODE_NUM 1000
#define BLOCK_SIZE 512//逻辑块的大小;
#define FILE_LEN 16*512
#define DATA 1024*1024//定义数据区的起点;

struct time//时间结构体;
{
short year;
short month;
short day;
short hour;
short min;
};
struct super_block/*管理块*/
{
int num_of_files;//登记系统中文件的总数;
bool block[BLOCK_NUM];//true表示不存在,false表示存在文件,该节点不可用;
bool inode[INODE_NUM];//标记inode的使用情况;
int first_inode_block;//第一个inode节点的偏移地址
int first_file_index;//文件目录的起点
bool flag[200];//true表示一个组中有空闲块,false表示该组已用满;
};

struct inode
{
int num;
char s_name[NAME_LENGTH];/*文件名*/
short blocks;//记录文件占用的磁盘块数目;
int s_file_length;/*文件的长度*/
int s_used_blocks[FILE_BLOCKS];/*文件使用的磁盘块号*/
};
/*打开文件表*/
struct file_opened
{
char name[NAME_LENGTH];
struct inode i_node;
struct file_opened*next;
};
struct file_index//文件目录结构;
{
char name[NAME_LENGTH];//存放文件名;
unsigned int num;//文件占用的i节点号;
struct file_index*next;//指向下一个节点的指针;
struct time s_time;//创建或最后一次修改文件的时间;
};
void save(FILE*fp,struct super_block*super,struct file_index*index,struct inode*newinode);
/*
功能:创建一个新的文件系统;
*/
/*得到系统的当前时间*/
struct time* gettime()
{
struct time* s_time;
s_time = (struct time*)malloc(sizeof(struct time));
time_t now_end; /* define 'now'. time_t is probably
* a typedef */
now_end = time((time_t *)NULL);
/* Get the system time and put it
* into 'now' as 'calender time' */
tm tim; //定义tm结构的变量tim
now_end = time(NULL);
tim = *localtime(&now_end); //利用localtime将时间从time_t格式转化到tm结构中
s_time->year = tim.tm_year;
s_time->month = tim.tm_mon;
s_time->day = tim.tm_mday;
s_time->hour = tim.tm_hour;
s_time->min = tim.tm_min;
return s_time;
}
FILE* create_new_file_sys(struct super_block* super)
{
FILE*fp;
char name[NAME_LENGTH];
struct inode *s_inode;//存放空闲i节点的号码
s_inode = (struct inode*)malloc(sizeof(struct inode));

cout<<"请输入你要创建的虚拟磁盘文件名:";
cin>>name;

if((fp = fopen(name, "w+"))==0)
{
cout<<"打开文件的时候出现错误!"<<endl;
return NULL;
};

fseek(fp,DEV_SIZE ,SEEK_SET);
fputc('#',fp);/*写入文件结束标志;*/
fseek(fp,0,SEEK_SET);
/*将超级块写入文件*/
/*初始化super*/
for(int i = 0;i<INODE_NUM;i++)
{
super->inode[i] = true ;//初始化i节点都可用;
}
for( i = 0;i<BLOCK_NUM;i++)//初始化数据块都可用;
super->block[i] = true;//true表示可用;

for(i = 0;i<200;i++)
super->flag[i] = true;
super->num_of_files = 0;
super->first_inode_block = sizeof(struct super_block);
super->first_file_index =
sizeof(struct super_block)+sizeof(struct inode)*INODE_NUM;
//将超级块写入虚拟磁盘开头;
if(fwrite(super,sizeof(struct super_block),1,fp)!= 1)
{
cout<<"写入超级块的时候出错!"<<endl;
return NULL;
}

fseek(fp,super->first_inode_block,SEEK_SET);//定位到i节点开始的地方;
for(i = 0;i<INODE_NUM;i++)
{
s_inode->num = i;
if(fwrite(s_inode,sizeof(struct inode),1,fp)!= 1)
{//循环的将inode写入磁盘;
cout<<"写入i节点的时候出现错误"<<endl;
return NULL;
}
}
cout<<"创建虚拟磁盘成功!"<<endl;
free(s_inode);
return fp;
}
/*初始化已经存在的虚拟磁盘文件*/
FILE* init(struct super_block*super,struct file_index*index)
{
char name[NAME_LENGTH];
FILE*fp;

cout<<"请输入你的虚拟磁盘文件名:";
cin>>name;

if((fp = fopen(name, "r+"))==NULL)
{
cout<<"打开文件的时候出现错误!"<<endl;
return NULL;
}
fseek(fp,0,SEEK_SET);

fread(super,sizeof(struct super_block),1,fp);//读出超级块信息;

if(super->num_of_files!=0)
{
struct file_index *p;
//struct file_index buff;
p = index;

rewind(fp);
fseek(fp,super->first_file_index,SEEK_SET);//定位到文件索引开始的地方;
struct file_index* node;
for(int i = 0;i<super->num_of_files;i++)
{ //建立文件目录链表;

node = (struct file_index*)malloc(sizeof(struct file_index));
if(fread(node,sizeof(struct file_index),1,fp)!=1)
{
cout<<"读取文件目录的时候发生错误!"<<endl;
break;
}
p->next = node;
p = p->next;
node->next = NULL;
}
}
return fp;
}


void open(struct super_block*super,struct file_index*index,FILE*fp,struct file_opened*fopened)
{
char name[NAME_LENGTH];
cout<<"请输入你要打开的文件名:";
cin>>name;
struct file_index*p;
for(p = index;p!=NULL;p = p->next)
{
if(strcmp(p->name,name) == 0)
break;
}

if(p!=NULL)//如果找到了文件;
{
char buff[512];
struct file_opened*f_open;
f_open = (struct file_opened*)malloc(sizeof(struct file_opened));
strcpy(f_open->name,name);
struct inode*out;
out = (struct inode*)malloc(sizeof(struct inode));
//定位到存放该文件i节点的地方;
rewind(fp);
int temp = super->first_inode_block+(p->num)*sizeof(struct inode);
fseek(fp,temp,SEEK_SET);
if(fread(out,sizeof(struct inode),1,fp)==1)//这个地方读写出现了问题啊,返回值为0;
{
struct file_opened*p;
for(p = fopened;p!=NULL;p = p->next)
if(strcmp(p->name,name)==0)break;
if(p == NULL)
{
f_open->i_node = *out;
f_open->next = fopened->next;
fopened->next = f_open;
}

int a = out->s_file_length/512;
int b = out->s_file_length%512;
cout<<"以下是文件的内容:"<<endl;
for(int i =0;i<a;i++)
{
rewind(fp);
fseek(fp,DATA+(out->s_used_blocks[i])*512,SEEK_SET);
if(fread(buff,sizeof(char)*512,1,fp)==1)
printf("%s",buff);
else cout<<"读磁盘时发生错误!"<<endl;
}
if(b!=0)
{
fseek(fp,DATA+(out->s_used_blocks[i])*512,SEEK_SET);
if(fread(buff,b,1,fp)==1)
{
for(int i = 0;i<b;i++)
printf("%c",buff[i]);//中间有一个异型符号要去掉啊!
cout<<endl;
}
else cout<<"读磁盘时发生错误!"<<endl;
}
}
}
else cout<<"没有找到你要打开的文件!"<<endl;
}

void edit(struct super_block*super,FILE*fp,struct file_index*index)
{
struct file_index *p;
char buff[512*16];
char buff1[512*16];
char name[NAME_LENGTH];
struct inode*node;
node = (struct inode*)malloc(sizeof(struct inode));
cout<<"请输入你要修改的文件的名字:";
cin>>name;
cout<<"请输入你要增加的信息:"<<endl;
gets(buff1);
int length = strlen(buff1);
for(p = index->next;p!=NULL;p = p->next)
if(strcmp(name,p->name)==0)break;
if(p!=NULL)
{

p->s_time =(* gettime());//得到创建文件的时间;
fseek(fp,super->first_inode_block+sizeof(struct inode)*(p->num),SEEK_SET);
fread(node,sizeof(struct inode),1,fp);
if((length+node->s_file_length)>512*16)
{cout<<"文件长度超出规定的最大长度!"<<endl;return;}
int a = node->blocks;
int b = node->s_file_length%512;
if(a==8){cout<<"文件长度已经达到最大!"<<endl;return;}

fseek(fp,DATA+node->s_used_blocks[a-1]*512,SEEK_SET);
if(b!=0)fread(buff,sizeof(char),b,fp);

for(int i = b;i<length+b;i++)
buff[i] = buff1[i-b];
int x = (length+b)/512;
int y = (length+b)%512;

if(y!=0)x++;
node->blocks = a-1+x;//添加后文件占用的磁盘块数;
node->s_file_length += length;
if(b!=0)a--;
int j= 0;
for(i = 0;j<x-1;j++)
for(;i<INODE_NUM;i++)
if(super->block[i] == true)
{ //为该文件分配空闲区;
node->s_used_blocks[j+a] = i;
super->block[i] = false;//修改该块的标志,表示被占用;
break;
}
char buff1[512];
for(i = 0;i<x-1;i++)
{
//定位到保存文件的数据块;
for(int j = 0;j<512;j++)
buff1[j] = buff[i*512+j];
fseek(fp,DATA+(node->s_used_blocks[i+a])*512,SEEK_SET);
if((fwrite(buff1,512,1,fp))!=1)
{
cout<<"创建文件时存储发生错误!"<<endl;
}
}

for( i = length+b-y;i<length+b;i++)
buff1[i-(length+b-y)] = buff[i];
rewind(fp);
int temp = DATA+(node->s_used_blocks[node->blocks-1])*512;
fseek(fp,temp,SEEK_SET);
if((fwrite(buff1,y,1,fp))!=1)
{
cout<<"修改文件时存储发生错误!"<<endl;
}

save(fp,super,index,node);
}
else
{
cout<<"该文件不存在!"<<endl;
return;
}
}

void create(struct super_block*super,FILE*fp,struct file_index*index)
{
struct file_index*newfile,*p;
newfile = (struct file_index*)malloc(sizeof(struct file_index));

char buff[512*16];
cout<<"请输入你要创建的文件的名字:";
cin>>newfile->name;
newfile->next = NULL;

for(p = index;p->next!=NULL;p = p->next)
if(strcmp(newfile->name,p->next->name)==0)
{
cout<<"该文件名已经存在了!"<<endl;
return;
}

for(int k = 0;k<INODE_NUM;k++)
if(super->inode[k] == true)break;
newfile->num = k;//分配存放文件的i节点号;
newfile->s_time =(* gettime());//得到创建文件的时间;
super->inode[k] = false;
super->num_of_files++;
//将新创建的文件插入目录,目录链表按照占用的i节点编号递增的顺序排列;

for(p = index;p->next!=NULL;p = p->next)
if((p->next->num)>(newfile->num))
{
newfile->next = p->next;
p->next = newfile;
}
if(p->next == NULL)
{
p->next = newfile;
newfile->next = NULL;
}

cout<<"请输入你要添加的文件的内容:"<<endl;
gets(buff);
struct inode*newnode = (struct inode*)malloc(sizeof(struct inode));
newnode->s_file_length = strlen(buff);
newnode->num = newfile->num;
int a = newnode->s_file_length/512;
int b= newnode->s_file_length%512;
if(b!=0)a++;
strcpy(newnode->s_name,newfile->name);
newnode->blocks = a;//该文件占用的磁盘块数;

for( int j = 0,i = 0;j<a;j++)
for(;i<INODE_NUM;i++)
if(super->block[i] == true)
{//为该文件分配空闲区;
newnode->s_used_blocks[j] = i;
super->block[i] = false;//修改该块的标志,表示被占用;
break;
}
char buff1[512];
for(i = 0;i<newnode->blocks-1;i++)
{
//定位到保存文件的数据块;
for(int j = 0;j<512;j++)
buff1[j] = buff[i*512+j];
fseek(fp,DATA+(newnode->s_used_blocks[i])*512,SEEK_SET);
if((fwrite(buff1,512,1,fp))!=1)
{
cout<<"创建文件时存储发生错误!"<<endl;
}
}
for( i = newnode->s_file_length - b;i<newnode->s_file_length;i++)
buff1[i-(newnode->s_file_length-b)] = buff[i];
rewind(fp);
int temp = DATA+(newnode->s_used_blocks[newnode->blocks-1])*512;
fseek(fp,temp,SEEK_SET);
if((fwrite(buff1,b,1,fp))!=1)
{
cout<<"创建文件时存储发生错误!"<<endl;
}
save(fp,super,index,newnode);
}
//保存更改后的超级块,文件目录,和文件的i节点信息;
void save(FILE*fp,struct super_block*super,struct file_index*index,struct inode*newinode)
{
rewind(fp);
fseek(fp,0,SEEK_SET);
fwrite(super,sizeof(struct super_block),1,fp);

//定位到存放该i节点的地方;
rewind(fp);
int temp = super->first_inode_block+(newinode->num)*sizeof(struct inode);
fseek(fp,temp,SEEK_SET);
fwrite(newinode,sizeof(struct inode),1,fp);

rewind(fp);
fseek(fp,super->first_file_index,SEEK_SET);
struct file_index* p ;

for(p = index->next;p!=NULL;p = p->next)
fwrite(p,sizeof(struct file_index),1,fp);
}

/*
功能:删除指定的文件;
*/
void deletefile(FILE*fp,struct super_block*super,struct file_index*index,struct file_opened* fopened)
{
char name[NAME_LENGTH];
cout<<"请输入你要删除的文件名:";
cin>>name;
struct file_index*p,*last;
for(p = index;p!=NULL;last = p,p = p->next)
{
if(strcmp(p->name,name) == 0)
break;
}
if(p!=NULL)//文件目录中找到了该文件名;
{
if(fopened->next != NULL)
{
if(fopened->next->next == NULL)//只有一个打开文件;
{
if(strcmp(fopened->next->name,name)==0)fopened->next = NULL;
}
else
{
struct file_opened*f_open;
struct file_opened*f_last;
for(f_open = fopened->next;f_open!=NULL;f_last = f_open,f_open = f_open->next)
if(strcmp(f_open->name,name)==0)//从打开文件表中删除该文件;
f_last->next = f_open->next;
}
}
struct inode* node;
node = (struct inode*)malloc(sizeof(struct inode));
//在文件目录链表中删除该节点;
last->next = p->next;
fseek(fp,super->first_inode_block+sizeof(struct inode)*(p->num),SEEK_SET);
if(fread(node,sizeof(struct inode),1,fp)!=1)
{
cout<<"删除文件的时候,在读取i节点信息时发生错误"<<endl;
return;
}
for(int i = 0;i<node->blocks;i++)
{
int temp = node->s_used_blocks[i];
super->block[temp] = true;//释放文件占据的磁盘块;
}
super->num_of_files--;//存储的文件总数减一;
}
else cout<<"没有找到你要删除的文件!"<<endl;
}
//显示文件目录;
void dir(struct file_index*index)
{
struct file_index* p;
cout<<"下面是目录信息:"<<endl;
cout<<"*******************************************"<<endl;
for(p = index->next;p!= NULL;p = p->next)
{
printf("%-10s",p->name);
cout<<"最后修改时间:"<<1900+p->s_time.year<<"年"<<p->s_time.month+1
<<"月"<<p->s_time.day<<"日"<<p->s_time.hour<<"时"
<<p->s_time.min<<"分"<<endl;
}
cout<<"*******************************************"<<endl;
}


void show_opened(struct file_opened*fopened)
{
struct file_opened*p;
cout<<"下面是已经打开的文件列表:"<<endl;
for(p = fopened->next;p!=NULL;p = p->next)
cout<<p->name<<endl;
}
/*
功能:将虚拟磁盘中的文件拷贝到指定的目录下;
入口参数:虚拟文件系统的文件目录表;
*/
void copyfile(struct super_block*super,struct file_index*index,FILE*fp)
{
FILE*cfp;
char srcname[NAME_LENGTH];
char dstname[50];
cout<<"请输入你要拷贝的源文件名"<<endl;
cin>>srcname;
cout<<"请输入目标文件名"<<endl;
cin>>dstname;
if((cfp = fopen(dstname, "w+"))==0)
{
cout<<"复制文件的时候出现错误!"<<endl;
return ;
};
struct file_index*p;
for(p = index->next;p!=NULL;p = p->next)
if(strcmp(p->name,srcname)==0)break;
if(p!=NULL)//源文件存在
{
struct inode*out;
out = (struct inode*)malloc(sizeof(struct inode));
int temp = super->first_inode_block+(p->num)*sizeof(struct inode);
fseek(fp,temp,SEEK_SET);
if(fread(out,sizeof(struct inode),1,fp)==1)//这个地方读写出现了问题啊,返回值为0;
{
char buff[512];
int a = out->s_file_length/512;
int b = out->s_file_length%512;
for(int i =0;i<a;i++)
{
rewind(fp);
fseek(fp,DATA+(out->s_used_blocks[i])*512,SEEK_SET);
if(fread(buff,sizeof(char)*512,1,fp)==1)
fwrite(buff,sizeof(char)*512,1,cfp);
else cout<<"读磁盘时发生错误!"<<endl;
}
if(b!=0)
{
fseek(fp,DATA+(out->s_used_blocks[i])*512,SEEK_SET);
if(fread(buff,b,1,fp)==1)
{
fwrite(buff,sizeof(char)*b,1,cfp);
}
else cout<<"读磁盘时发生错误!"<<endl;
}
}
}
fclose(cfp);
}

void main( void )
{
FILE* fp ;//虚拟磁盘文件的指针;
struct super_block* super;
struct file_index *index = NULL;
struct file_opened *fopened;

super = (struct super_block*)malloc(sizeof(struct super_block));
index = (struct file_index*)malloc(sizeof(struct file_index));
fopened = (struct file_opened*)malloc(sizeof(struct file_opened));
index->next = NULL;
fopened->next = NULL;

char ch;
cout<<"创建一个新的虚拟磁盘文件吗?(y/n)";
cin>>ch;
if(ch == 'y'||ch == 'Y')
{
fp = create_new_file_sys( super );
}

else fp = init(super,index);

while(1)
{
int choice;
cout<<"*******************************************"<<endl;
cout<<"请选择相应的操作:"<<endl;
cout<<"1:打开文件"<<endl;
cout<<"2:创建文件"<<endl;
cout<<"3:复制文件"<<endl;
cout<<"4:删除文件"<<endl;
cout<<"5:修改文件"<<endl;
cout<<"6:显示目录"<<endl;
cout<<"7:显示已经打开的文件列表"<<endl;
cout<<"8:安全退出"<<endl;
cin>>choice;
switch(choice)
{
case 1: open(super,index,fp,fopened);
break;
case 2: create(super,fp,index);
break;
case 3: copyfile(super,index,fp);
break;
case 4: deletefile(fp,super,index,fopened);
break;
case 5: edit(super,fp,index);
break;
case 6: dir(index);
break;
case 7: show_opened(fopened);
break;
case 8: fclose(fp);
free(super);
free(index);
exit(0);
default: exit(0);
}
}
}

 

本文地址:http://www.45fan.com/a/question/73332.html
Tags: 实现 文件 系统
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部