16281053_杨瑷彤_操作系统第五次实验-文件系统
源代码链接:https://github.com/rdjyat/operating-system/tree/master/操作系统实验五
1.实验简介
本实验要求在模拟的I/O系统之上开发一个简单的文件系统。用户通过create, open, read等命令与文件系统交互。文件系统把磁盘视为顺序编号的逻辑块序列,逻辑块的编号为0至L − 1。I/O系统利用内存中的数组模拟磁盘。
2.程序设计
2.1 数据结构设计
1、模拟磁盘设计:实际物理磁盘的结构是多维的:有柱面、磁道、扇区等概念。系统的任务是隐藏磁盘的结构细节,把磁盘以逻辑块的面目呈现给文件系统。逻辑块顺序编号,编号取值范围为0至L -1 ,其中L表示磁盘的存储块总数。实验中,我们可以利用字符数组disk[L][B]构建磁盘模型,其中B 表示每个存储块的长度。
2、文件结构体设计,使用结构体表示文件,包含文件长度以及分配到的块号数组。
typedef struct FileDescriptor//文件描述符
{
int filelength; //文件长度。单位,字节
int fileblock[Block_Length]; //分配到的块号数组
}FileDescriptor;
3、目录结构体设计
typedef struct directory//目录项结构体,用来描述目录下的每一个文件
{
char filename[Name_Length]; //文件名
int index;
}directory;
2.2 全局变量设计
#define B 512 //定义存储块的长度B字节
#define L 100 //定义磁盘的存储块总数L,逻辑号0-(L-1)
#define K 5 //磁盘的前k 个块是保留区
#define Block_Length 3 //定义文件磁盘块号数组长度为3
#define Name_Length 12 //定义文件名的长度个字节
#define maxopen 20//打开文件表中最多同时存在20个文件
char disk[L][B]; //用字符数组构建磁盘模型
char bitmap[L];
int describ_maxnum; //文件描述符的最大数量,也是文件的最多数量
int file_num;//当前文件数量
int directory_block_num;//目录文件已分得的磁盘块数
int openfile_num;//当前处于打开状态的文件的数量
2.3 主要函数设计
a. I/O系统函数
1、读逻辑块
/*
* 函数名:read_block
* 功能:该函数把逻辑块i 的内容读入到指针p 指向的内存位置,拷贝的字符个数为存储块的长度B
* 参数: int i
* char *p
* 返回值:
* 无
*/
void read_block(int i,char*p)
{
memcpy(p,&disk[i][0],B);
}
2、写入逻辑块
/*
* 函数名:write_block
* 功能:该函数把指针p 指向的内容写入逻辑块i,拷贝的字符个数为存储块的长度B。
* 参数: int i
* char *p
* 返回值:
* 无
*/
void write_block(int i,char*p)
{
memcpy(&disk[i][0],p,B);
}
3、保存至文件,模拟磁盘写
/*
* 函数名:save
* 功能:把数组disk 存储到文件,模拟磁盘写入过程
* 参数:
* 无
* 返回值:
* 无
*/
void save()
{
FILE *fp;
fp = fopen("disk.txt","w");
if(fp == NULL)
{
printf("error,cannot open the file!\n");
}
fwrite(&disk[0][0],sizeof(char),L*B,fp);
fclose(fp);
}
4、文件内容恢复到数组
/*
* 函数名:load
* 功能:把文件内容恢复到数组
* 参数:
* 无
* 返回值:
* 无
*/
void load()
{
FILE *fp;
fp = fopen("disk.txt","r");
if(fp == NULL)
{
printf("error,cannot open the file!\n");
}
for(int i=0;i<(L*B);i++)
fread(&disk[0][0],sizeof(char),L*B,fp);
}
** b.文件系统函数**
1、初始化函数
/*
* 函数名:Init
* 功能:初始化文件系统:
初始化位图(0表示空闲,1表示被占用);
初始化0号文件描述符;
* 参数:
* 无
* 返回值:
* 无
*/
void Init()
{
int i;
//初始化位图
//前k块保留,这里默认被使用
for( i = 0 ; i < K ; ++i )
{
bitmap[i] = '1';
disk[0][i] = '1';//磁盘的前k个单元用来存储对应的bitmap
}
for( i = K ; i < L ; ++i )
{
bitmap[i] = '0';
disk[0][i] = '0';
}
file_num = 0;//初始化时,系统中文件的数量为0
//设置文件描述符
int describ_start = sizeof(bitmap);
pdescrib = (FileDescriptor*)&(disk[0][describ_start]);
//前K块剩下的空间用来村文件描述符
describ_maxnum = (K*B-describ_start)/sizeof(FileDescriptor);
FileDescriptor* temp;
for(temp = pdescrib;temp<pdescrib+describ_maxnum;temp++)
{
temp->filelength = -1;
for( i = 0 ; i < Block_Length ; ++i )
{
//初始化每个文件磁盘块未被使用的
temp->fileblock[i] = -1;
}
}
pdescrib->filelength = 0;//根目录初始化时没有文件
directory_block_num = 0;//初始化时,目录文件并不占有任何磁盘
save();
/*初始化文件打开表,清空表项*/
for(i=0;i<maxopen;i++)
{
openlist[i].index = -1;
openlist[i