操作系统实验八 文件结构 模拟设计MS-DOS操作系统中磁盘文件的存储结构
一、实验内容
1、把文件的逻辑结构转换成存储结构
2、设计便于顺序存取和直接存取的文件存储结构。
二、实验目的
1、研究用户概念中的信息组织方式
2、理解文件的逻辑结构、存取结构、存取方式之间的联系
3、模拟设计文件的存储结构
三、实验题目
1、第一题:模拟设计MS-DOS操作系统中磁盘文件的存储结构。
[提示]:
⑴当用户对记录式文件采用顺序存以方式时,用户总是依次地访问一个个逻辑记录,即当访问了第i个记录后,下次总是访问第i+1个记录。所以,当用户采用顺序存取方式访问文件时,只要给出访问要求(读或写)而无需再指出要访问的记录号。
⑵采用链接文件结构,只有读出一个物理块信息后才能从链接字中得知下一个物理块号。所以,当用户要在文件中插入一些信息时,文件系
统必须多次地请求启动磁盘读出信息才能做插入工作。
• MS-DOS操作系统对链接文件结构作了改进,它是把所有的链接指针集中在一起,存放在文件定位表FAT中。查找链接字时不必读出物理块信息可直接从FAT中得到。
• 其设计思想是:假定磁盘上共有N个物理块可供使用,FAT就有N项,初始化时为全“0”,表示对应的物理块均可使用,当要存放文件时,从FAT中寻找为“0”的项,其对应的物理块用来存放文件信息,把文件的链接指针(指出物理块号)登记在FAT中,文件第一块块号登记在文件目录中。
⑶假定磁盘存储空间共有32个物理块,模拟设计文件定位表FAT。文件定位表可以用一个一维数组FAT[031]来定义,其中一个元素与一个物理块对应。当FAT[i]=0时,表示第i块为空闲块;当FAT[i]=FFF时,表示链接文件到第i块结束;当在0~FFF时,其值指示链接文件中下一个物理块号。
⑷每个物理块只能存放一个逻辑记录,设计一个程序把文件的逻辑结构模拟转换成MS-DOS的链接结构。
• 要求保存一个已经在主存中的文件时,给出文件名和文件的逻辑记录长度及个数,对一个已经保存的文件,允许用户插入新记录。用键输入来模拟用户的要求,输入信息为:“存” 文件名 逻辑记录长度 逻辑记录个数“插入” 文件名 逻辑记录号
• 模拟程序的算法如下图所示:
⑸ 假设系统中已经有两个链接文件,其链接情况由FAT表指出(链接情况学生自定),现又要保存一个新文件,然后对已保存的文件插入一个新记录。运行你所设计的程序,观察其结果。
思路
设计一个小菜单,有五个功能:1、新建文件2、修改文件3、删除文件4、查看文件目录5、查看文件定位表(FAT)
用链表结构表示文件目录,每次新建文件时在链表头部插入新的文件。
使用的数据结构如下:
struct Page//文件目录
{
string name;//文件名
int num;//起始块号
int length;//文件长度
Page *pre;
Page *next;
};
struct Node//物理块
{
int num;//为0时为空
string str;//逻辑记录
};
具体代码:
#include <iostream>
using namespace std;
struct Page//文件目录
{
string name;//文件名
int num;//起始块号
int length;//文件长度
Page *pre;
Page *next;
};
struct Node//物理块
{
int num;//为0时为空
string str;//逻辑记录
};
int frees=32;//空闲物理块号
Node node[32];
void init(Page *head)//初始化
{
for(int i=0;i<32;i++)
{
node[i].num=0;
node[i].str="";
}
head->name=" ";
head->num=-1;
head->length=0;
head->pre=NULL;
head->next=NULL;
}
void create(Page *head)//新建文件
{
cout<<"请输入文件名\n";
string str;
cin>>str;
Page *temp=new Page();
Page *temp1=new Page();
temp->name=str;
for(temp1=head;temp1!=NULL;temp1=temp1->next) //文件名已存在
{
if(str==temp1->name)
{
cout<<"文件名已存在,请重新输入\n";
delete temp;
delete temp1;
return ;
}
}
cout<<"请输入文件长度\n";
int leng;
cin>>leng;
if(leng>frees) //判断是否有足够的空闲块
{
cout<<"磁盘空间不足\n";
delete temp;
return ;
}
frees-=leng;
cout<<"请输入文件内容\n";
string str1[leng];
for(int i=0;i<leng;i++)//输入文件内容
{
cin>>str1[i];
}
int cou=0;
for(int i=0;i<leng;i++)
{
for(int j=0;j<32;j++)
{
if(node[j].num==0)//查找空闲块
{
if(i==0) //起始块号
{
cou=j;
temp->num=j;
temp->length=leng;
temp->next = head->next; //头插法插入新作业
if(head->next != NULL)
head->next->pre = temp;
temp->pre = head;
head->next = temp;
node[j].str=str1[i];
node[cou].num=-1;
}
else if(i==leng-1)//末尾
{
node[j].str=str1[i];
node[cou].num=j;
node[j].num=-1;
}
else//中间
{
node[j].str=str1[i];
node[cou].num=j;
node[j].num=-1;
cou=j;
}
break;
}
}
}
cout<<"新建成功\n";
}
void change(Page *head)//插入内容,设定每次只能插入一段内容
{
if(frees==0) {cout<<"无空闲块\n";return ;}
cout<<"请输入要修改的文件名\n";
string str;
cin>>str;
Page *temp=new Page();
for(temp=head;temp!=NULL;temp=temp->next)
{
if(temp->name==str)
{
temp->length++;
cout<<"在第几段文件插入\n";
int nu;
cin>>nu;
cout<<"请输入文件内容\n";
string str1;
cin>>str1;
int temp1=temp->num;
string temp2=str1;
int i=1;
string nk;
while(1)//插入位置之后的内容后移
{
if(i==temp->length-1)
{
for(int k=0;k<32;k++)
{
if(node[k].num==0)
{
string nk2=temp2;
temp2=node[temp1].str;
node[temp1].num=k;
node[temp1].str=nk2;
temp1=k;
break;
}
}
node[temp1].str=temp2;
node[temp1].num=-1;
break;
}
nk=temp2;
temp2=node[temp1].str;
if(i>nu) node[temp1].str=nk;
if(i==nu) node[temp1].str=str1;
temp1=node[temp1].num;
i++;
}
cout<<"插入成功\n";
frees--;//空闲块减一
return;
}
}
cout<<"文件名不存在"<<endl;
}
void shanchu(Page *head)//删除
{
cout<<"请输入要删除的文件名\n";
string str;
cin>>str;
Page *temp=new Page();
for(temp=head;temp!=NULL;temp=temp->next)
{
if(temp->name==str)
{
int i=temp->num;
while(1)
{
frees++;//每次空闲块加1
node[i].str="";
if(node[i].num==-1)
{
node[i].num=0;
break;
}
int temp1=node[i].num;
node[i].num=0;
i=temp1;
}
temp->pre->next=temp->next;//删除输入的文件
if(temp->next!=NULL) temp->next->pre=temp->pre;
cout<<"删除成功\n";
delete temp;
return ;
}
}
cout<<"文件不存在\n";
}
void print1(Page *head)//打印文件目录
{
cout<<"文件目录如下:\n";
cout<<"文件名 文件长度\n";
Page *temp=new Page();
for(temp=head->next;temp!=NULL;temp=temp->next)
{
cout<<temp->name<<" "<<temp->length<<"\n";
}
delete temp;
}
void print2()//打印文件定位表
{
cout<<"块号 指向 内容"<<endl;
for(int i=0;i<32;i++)
{
cout<<i<<" "<<node[i].num<<" "<<node[i].str<<endl;
}
}
int main()
{
Page *head=new Page();
init(head);
while(1)
{
int choice;
cout<<".....................................\n";
cout<<"1、新建文件\n2、修改文件\n3、删除文件\n4、查看文件目录\n5、查看文件定位表(FAT)\n";
cout<<".....................................\n";
cin>>choice;
switch(choice)
{
case 1:
create(head);
break;
case 2:
change(head);
break;
case 3:
shanchu(head);
break;
case 4:
print1(head);
break;
case 5:
print2();
break;
default:
cout<<"没有此操作,请重新输入\n";
}
}
}