文件系统存储空间管理模拟实验报告.docx
《文件系统存储空间管理模拟实验报告.docx》由会员分享,可在线阅读,更多相关《文件系统存储空间管理模拟实验报告.docx(29页珍藏版)》请在冰豆网上搜索。
文件系统存储空间管理模拟实验报告
课程名称计算机操作系统实验名称文件系统存储空间管理模拟姓名学号
专业班级实验日期
成绩指导老师
1、实验目的
根据提出的文件分配和释放请求,动态显示磁盘空闲空间的
态以及文件目录的变化,以位示图和索引分配为例:
每次执行请求后要求显示或打印位示图的修改位置、分配和回收磁盘的物理块地址、更新的位示图、目录。
2、实验原理
用数组表示位示图,其中的每一位对应磁盘一个物理块的状态,0表示、空闲,1表示分配;当请求分配一个磁盘块时,寻找到数组中为0的位,计算相对磁盘块号,并计算其在磁盘中的物理地址(柱面号、磁道号、物理块号),并将其状态由0变到1。
当释放某一物理块时,已知其在磁盘中的物理地址,计算其相对磁盘块号,再找到位示图数组中的相应位,将其状态由1变为0。
3、主要仪器设备
PC机(含有VC)
4、实验内容与步骤
实验内容:
1.模拟文件空间分配、释放过程,可选择连续分配、链式分配、
索引分配方法;2.文件空闲空间管理,可采用空白块链、空白目录、位示图方法;
步骤如下:
1.输入磁盘基本信息参数,计算位示图大小,并随机初始化位示图;
(1)磁盘基本信息:
磁盘柱面数m,每柱面磁道数p,每磁道物理块数q;
(2)假设采用整数数组存放位示图,则数组大小为:
Size=ceil((柱面数*每柱面磁道数*每磁道物理块数)/(sizeof(int)*8))
(3)申请大小为size的整数数组map,并对其进行随机初始化。
例如:
假设m=2,p=4,q=8,共有64个磁盘块,若sizeof(int)=2,则位示图大小为4,map[4]如下:
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
map[0]
0
0
1
1
0
1
0
0
1
1
0
0
1
0
1
0
map[1]
1
0
1
0
1
1
0
0
0
0
1
1
0
0
0
0
map[2]
0
1
1
0
0
1
1
1
0
0
1
1
0
0
1
map[3]
1
0
0
0
1
0
0
0
0
1
1
0
0
1
1
0
位示图中每一位对应的相对磁盘块号如下图,磁盘块号由小到大对应于数组的低地址到高地址位上。
即map[0]的第0位到第15位分别对应0号磁盘块到15号磁盘块的状态,map[1]的第0位到第15位对应16号磁盘块到31号磁盘块的状态,以此类推。
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
map[0]
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
map[1]
31
30
29
28
27
26
25
24
23
22
21
20
19
18
17
16
map[2]
47
46
45
44
43
42
41
40
39
38
37
36
35
34
33
32
map[3]
63
62
61
60
59
58
57
56
55
54
53
52
51
50
49
48
如上表所示,29号磁盘的状态存在map[1]中,对应于第13位;
2.输出初始位示图信息;
3.输入文件分配或释放请求,
(1)格式:
“+文件名申请块数”或“-文件名”
“+”表示申请文件分配,“-”表示删除文件
如:
+F15
4.根据请求完成相应操作。
(1)若为分配申请x个盘块,则在位示图中找到x个为0的位,将其修改为“1”,计算相应具体物理设备的柱面号C、磁道号H和物理块号R,并将CHR地址或相对磁盘块号记录在文件目录中。
输出位示图修改位置、分配的磁盘块CHR地址、修改后的目录和位示图信息。
否则,空间不够,退出执行下一条请求;
●计算公式如下:
a.已知位示图中的下标i,j,计算相对块号
Block=i*sizeof(int)*8+j
b.已知相对块号计算柱面、磁道、物理块号如下:
柱面号C=相对块号/(每柱面磁道数*每磁道物理块数)
磁道号H=相对块号%(每柱面磁道数*每磁道物理块数)/每磁道物理块数
物理块号R=相对块号%每磁道物理块数
●文件目录如下(以索引表分配为例):
文件名
首个物理块CHR地址
块个数
索引表
beta
(0,0,0)
2
(0,0,0)(0,0,1)
Alpha
(2,3,0)
3
(2,3,0)
Toyota
4
3
(4912)…
(
Sony
文件名
首个物理块地址(相对)
块个数
索引表
beta
0
2
(0,2,3)…
Alpha
3
3
(3,6,7)…
Toyota
8
3
(8,9,12)…
(2)若为删除申请,则从目录中找到要删除的文件所在的目录项,读取索引表,依次读
取文件相应的盘块CHR地址,计算该盘块的相对磁盘块号,再计算其相应信息在位示图中的位置(i,j),将位示图中的相应位有“1”改为“0”,并从目录中删除该目录项。
输出删除的磁盘块CHR地址、相应位示图修改位置、修改过的位示图和目录。
计算过程如下:
相对磁盘块号=柱面号*每柱面磁道数*每磁道物理块数+
磁道号*每磁道物理块数+物理块号
i=相对磁盘块号/(sizeof(int)*8)
j=相对磁盘块号%(sizeof(int)*8)
5、实验流程图
图一文件空闲区分配算法
图二文件空闲区回收算法
6、实验代码
#include"stdio.h"
#include
#include
#include
intphysic[100];//文件地址缓冲区
intstyle=1;//文件的类型
charcur_dir[10]="root";//当前目录
structcommand
{charcom[10];
}cmd[13];
structblock
{intn;//空闲的盘快的个数
intfree[50];//存放空闲盘快的地址
inta;//模拟盘快是否被占用
}memory[20449];
structblock_super
{intn;//空闲的盘快的个数
intfree[50];//存放进入栈中的空闲块
intstack[50];//存放下一组空闲盘快的地址
}super_block;
structnode//i结点信息
{intfile_style;//i结点文件类型
intfile_length;//i结点文件长度
intfile_address[100];//i结点文件的物理地址
}i_node[640];
structdir//目录项信息
{charfile_name[10];//文件名
inti_num;//文件的结点号
chardir_name[10];//文件所在的目录
}root[640];
voidformat()//格式化
{inti,j,k;
super_block.n=50;
for(i=0;i<50;i++)//超级块初始化
{super_block.free[i]=i;//存放进入栈中的空闲块
super_block.stack[i]=50+i;//存放下一组的盘块
}
for(i=0;i<640;i++)//i结点信息初始化
{for(j=0;j<100;j++)
{i_node[i].file_address[j]=-1;//文件地址
}
i_node[i].file_length=-1;//文件长度
i_node[i].file_style=-1;//文件类型
}
for(i=0;i<640;i++)//根目录区信息初始化
{strcpy(root[i].file_name,"");
root[i].i_num=-1;
strcpy(root[i].dir_name,"");
}
for(i=0;i<20449;i++)//存储空间初始化
{memory[i].n=0;//必须有这个
memory[i].a=0;
for(j=0;j<50;j++)
{memory[i].free[j]=-1;
}
}
for(i=0;i<20449;i++)//将空闲块的信息用成组链接的方法写进每组的最后一个块中
{//存储空间初始化
if((i+1)%50==0)
{k=i+1;
for(j=0;j<50;j++)
{if(k<20450)
{memory[i].free[j]=k;//下一组空闲地址
memory[i].n++;//下一组空闲个数注意在memory[i].n++之前要给其赋初值
k++;
}
else
{memory[i].free[j]=-1;
}
}
memory[i].a=0;//标记为没有使用
continue;//处理完用于存储下一组盘块信息的特殊盘块后,跳过本次循环
}
for(j=0;j<50;j++)
{memory[i].free[j]=-1;
}
memory[i].n=0;
}
printf("已经初始化完毕\n");
printf("进入UNIX文件模拟............\n\n");}
voidwrite_file(FILE*fp)//将信息读入系统文件中
{inti;
fp=fopen("system","wb");
for(i=0;i<20449;i++)
{fwrite(&memory[i],sizeof(structblock),1,fp);
}
fwrite(&super_block,sizeof(structblock_super),1,fp);
for(i=0;i<640;i++)
{write(&i_node[i],sizeof(structnode),1,fp);
}
for(i=0;i<640;i++)
{fwrite(&root[i],sizeof(structdir),1,fp);
}
fclose(fp);
}
voidread_file(FILE*fp)//读出系统文件的信息
{inti;
fp=fopen("system","rb");
for(i=0;i<20449;i++)
{fread(&memory[i],sizeof(structblock),1,fp);
}
fread(&super_block,sizeof(structblock_super),1,fp);
for(i=0;i<640;i++)
{fread(&i_node[i],sizeof(structnode),1,fp);
}
for(i=0;i<640;i++)
{fread(&root[i],sizeof(structdir),1,fp);
}
fclose(fp);
}
voidcallback(intlength)//回收磁盘空间
{inti,j,k,m,q=0;
for(i=length-1;i>=0;i--)
{
k=physic[i];//需要提供要回收的文件的地址
m=49-super_block.n;//回收到栈中的哪个位置
if(super_block.n==50)//注意当super_block.n==50时m=-1;的值
{//super_block.n==50的时候栈满了,要将这个栈中的所有地址信息写进下一个地址中
for(j=0;j<50;j++)
{
memory[k].free[j]=super_block.free[j];
}
super_block.n=0;
memory[k].n=50;
}
memory[k].a=0;
if(m==-1)
{m=49;//将下一个文件地址中的盘块号回收到栈底中,这个地址中存放着刚才满栈的地址的信息
}
super_block.free[m]=physic[i];//将下一个文件地址中的盘块号回收到栈中
super_block.n++;
}
}
voidallot(intlength)//分配空间
{inti,j,k,m,p;
for(i=0;i{
k=50-super_block.n;//超级块中表示空闲块的指针
m=super_block.free[k];//栈中的相应盘块的地址
p=super_block.free[49];//栈中的最后一个盘块指向的地址
if(m==-1||memory[p].a==1)//检测是否还有下一组盘块
{
printf("内存不足,不能够分配空间\n");
callback(length);
break;
}
if(super_block.n==1)
{
memory[m].a=1;//将最后一个盘块分配掉
physic[i]=m;
super_block.n=0;
for(j=0;j{
super_block.free[j]=memory[m].free[j];
super_block.n++;
}
continue;//要跳过这次循环,下面的语句在IF中已经执行过
}
physic[i]=m;//栈中的相应盘块的地址写进文件地址缓冲区
memory[m].a=1;
super_block.n--;
}
}
voidcreate_file(charfilename[],intlength)//创建文件
{
inti,j;
for(i=0;i<640;i++)
{
if(strcmp(filename,root[i].file_name)==0)
{
printf("文件已经存在,不允许建立重名的文件\n");
return;
}
}
for(i=0;i<640;i++)
{
if(root[i].i_num==-1)
{
root[i].i_num=i;
strcpy(root[i].file_name,filename);
strcpy(root[i].dir_name,cur_dir);//把当前目录名给新建立的文件
i_node[i].file_style=style;
i_node[i].file_length=length;
allot(length);
for(j=0;j{
i_node[i].file_address[j]=physic[j];
}
break;
}
}
}
voidcreate_dir(charfilename[])//创建目录
{style=0;//0代表文件类型是目录文件
create_file(filename,4);
style=1;//用完恢复初值,因为全局变量,否则
}
voiddel_file(charfilename[])//删除文件
{
inti,j,k;
for(i=0;i<640;i++)
{if(strcmp(filename,root[i].file_name)==0)
{
k=root[i].i_num;
for(j=0;j{
physic[j]=i_node[k].file_address[j];
}
callback(i_node[k].file_length);//调用回收函数
for(j=0;j<100;j++)//删除文件后要将文件属性和目录项的各个值恢复初值
{
i_node[k].file_address[j]=-1;//地址恢复初值
}
strcpy(root[i].file_name,"");//文件名恢复初值
root[i].i_num=-1;//目录项的I结点信息恢复初值
strcpy(root[i].dir_name,"");//目录项的文件目录信息恢复初值
i_node[k].file_length=-1;//文件长度恢复
i_node[k].file_style=-1;//文件类型恢复初值
break;
}
}
if(i==640)
{
printf("不存在这个文件\n");
}
}
voiddel_dir(charfilename[])//删除目录需要判断目录下时候为空,不为空就不删除
{
inti,j,k;
for(i=0;i<640;i++)//还要加条件判断要删除的目录是不是当前目录
{
k=root[i].i_num;//找到目录名字
if(strcmp(root[i].file_name,filename)==0&&strcmp(cur_dir,filename)!
=0&&(i_node[k].file_style)==0)
{
for(j=0;j<640;j++)
{
if(strcmp(filename,root[j].dir_name)==0)
{
printf("目录不为空不能直接删除\n");
break;
}
}
if(j==640)
{
del_file(filename);
break;
}
break;
}
}
if(i==640)
{
printf("这个不是目录文件或者不存在这个目录,或者你要删除的是当前目录\n");
}
}
voiddisplay_curdir()//显示当前目录下的文件列表
{
inti,k;
printf("\t\t文件名字文件类型文件长度所属目录\n");
for(i=0;i<640;i++)
{
if(strcmp(cur_dir,root[i].dir_name)==0)//查询文件中所在目录信息和当前目录信息相同的数据
{
k=root[i].i_num;
printf("\t\t%s\t",root[i].file_name);//文件名
printf("\t%d\t",i_node[k].file_style);//文件的类型
printf("%d\t",i_node[k].file_length);//文件的长度
printf("%s\n",root[i].dir_name);//文件所在的目录
}
}
}
voiddisplay_dir(charfilename[])//进入指定的目录
{
inti,k;
for(i=0;i<640;i++)
{
k=root[i].i_num;//判断文件类型是不是目录类型
if((strcmp(filename,root[i].file_name)==0)&&(i_node[k].file_style==0))
{
strcpy(cur_dir,filename);//将要进入的指定目录设置为当前目录赋值不要反了strcpy(目的,源)
break;
}
}
if(i==640)
{
printf("没有这个目录\n");
}
}
voidopen_file(charfilename[])//打开文件
{
inti,j,k;
printf("\t\t文件名字文件类型文件长度所属目录\n");
for(i=0;i<640;i++)
{
k=root[i].i_num;
if(strcmp(filename,root[i].file_name)==0&&(i_node[k].file_style==1))
{
printf("\t\t%s\t",root[i].file_name);//文件名
printf("\t%d\t",i_node[k].file_style);//文件的类型
printf("%d\t",i_node[k].file_length);//文件的长度
printf("%s\n",root[i].dir_name);//文件所在的目录
printf("\t\t文件占用的物理地址\n");
for(j=0;j{
printf("%d",i_node[k].file_address[j]);//文件具体占用的盘块号
}
printf("\n");
break;
}
}
if(i==640)
{
printf("没有这个文件或者这个文件不是正规文件\n");
}
}
voidback_dir()//返回上一级目录
{
inti,k;
for(i=0;i<640;i++)//查询和当前目录名相同的目录文件名
{
k=root[i].i_num;
if(strcmp(cur_dir,root[i].file_name)==0&&(i_node[k].file_style==0))
{
strcpy(cur_dir,root[i].dir_name);//将查询到的目录文件名所在的目录赋值给当前目录
}
}
}
voiddisplay_sys()//显示系统信息(磁盘使用情况)
{
inti,m,k=0;
for(i=0;i<20449;i++)
{
if(memory[i].a==0)
k++;
}
m=20449-k;
printf("空闲的盘块数是:
\t");
printf("%d\n",k);
printf("使用的盘块数是:
\t");
printf("%d\n",m);
}
voidhelp()//显示帮助信息
{printf("************************