//[原创][5.磁盘存储空间的管理/十大题型]算法全实现
/*五 磁盘存储空间的管理
主要有:
位示图 和内存的位示差不多
空闲块表 和可变内存管理差不多
空闲块链 主要是UNIX成组链接法的设计与实现
UNIX系统文件管理成组连接算法说明
UNIX系统文件管理成组连接算法:
把空闲块分成若干组,把指向一组中各空闲块的指针集中一起。
这样既可方便查找,又可减少为修改指针而启动磁盘的次数。
UNIX系统:采用空闲块成组连接的方法。
UNIX系统把每100个空闲块作为一组,每一组的第一个空闲块中登记下一组空闲块的块号和空闲块数,
余下不足100块的那部分空闲块的块号及块数登记在一个专用块中,登记最后一组块号的那个空闲块其中第2个单元填“0”,
表示该块中指出的块号是最后一组的块号,空闲块链到此结束。
系统初始化时先把专用块内容读到内存,当需分配空闲块时,就直接在内存中可找到哪些块强障械模糠峙湟豢楹蟀芽障锌槭。
但要把一组中的第一个空闲块分配出去之前应把登记在该块中的下一组的块号及块数保存到专用块中。
当一组空闲块被分配完后,则再把专用块的内容读到内存,指出另一组可供分配的空闲块。当归还一块时,
只要把归还块的块号登记到当前组中且空闲块数加1。如果当前组已满100块,则把内存中的内容写到归还的那块中,
该归还块作为新组的第一块。假设初始化时系统已把专用块读入内存L单元开始的区域中,分配和回收的算法如下:
分配一个空闲块
查L单元内容(空闲块数):
当空闲块数1 i =L+空闲块数;
从i单元得到一空闲块号;
把该块分配给申请者;
空闲块数减1。
当空闲块数=1 取出L+1单元内容(一组的第一块块号或0);
其值=0无空闲块,申请者等待
不等于零把该块内容复制到专用块;
该块分配给申请者;
把专用块内容读到主存L开始的区域。
归还一块
查L单元的空闲块数;
当空闲块数100 空闲块数加1;
j =L+空闲块数;
归还块号填入j单元。
当空闲块数=100 把主存中登记的信息写入归还块中;
把归还块号填入L+1单元;
将L单元置成1。
采用成组连接后,分配回收磁盘块时均在内存中查找和修改,只是在一组空闲块分配完或空闲的磁盘块构成一组时才启动磁盘读写。
比单块连接方式效率高。
6月5日下午题是模拟UNIX的成组链接法的设计与实现
主要考的是利用文件输入一堆空闲块的号码,然后利用UNIX的成组链接法的管理方法,按照10块成一组,
并且可以实现输入一个数字N,然后把N个空闲块占用,输出专用块的大小,空闲号。如果专用块的空间不够,
把下一个成组的内容考入专用块。输出不要求写文件,但是要显示在屏幕上。
本程序包括:UNIX的成组链接法的设计与实现
*/
#include<stdio.h>
#include<string.h>
#include<iostream.h>
#ifndef UINT
#define UINT unsigned int
#endif //UINT
const UINT MAXGROUP=10;//定义组的大小
const UINT MAXJOB=100;//定义一个作业最大能申请的块数
//结构体定义
typedef struct node{
int quantity; //组中元素计数器:所存储的空闲块个数
int cell[MAXGROUP]; //组中元素存放的数组:所存储的空闲块号
struct node *next; //链表下一个节点的指针
}group;
typedef struct node1{
char name[20]; //作业名
int quantity; //作业个数
int cell[MAXJOB]; //作业号数组
struct node1 *next; //链表下一个节点的指针
}job;
/* 定义组链表头,这里定义为全局变量 */
group* g_GroupHead;
unsigned int g_UItotal;
job *g_JobHead;
//初始化组函数
group *initial()
{
UINT i;
group *p;
p=new group;
p->quantity=0;
p->next=NULL;
for(i=0;i<MAXGROUP;i++)
{
p->cell[i]=-1;
}
return p;
}
//初始化作业函数
job *initial_job()
{
UINT i;
job *p;
p=new job;
strcpy(p->name,"");
p->quantity=0;
p->next=NULL;
for(i=0;i<MAXGROUP;i++)
{
p->cell[i]=-1;
}
return p;
}
//读入空闲块流文件
void readData()
{
FILE *fp;
char fname[20] = "TestUnix.txt";
int temp;
group *p;
while( (fp=fopen(fname,"r")) == NULL )
{
//打开默认的文件TestUnix.txt
//fp=fopen("TestUnix.txt","r");
if (NULL == fp)
{
cout<<"错误,文件"<< fname << "打不开,请检查文件名:)"<<endl;
}
//打开成功后就不要输入文件名了直接返回
else
{
break;
}
//如果默认的文件打不开,手动输入文件名打开
cout<<"请输入初始空闲块数据文件名:";
cin>>fname;
}
cout<<"=================================================="<<endl;
cout<<"从文件" << fname << "读入的初始空闲块号为:";
while(!feof(fp))
{
fscanf(fp,"%d ",&temp);
if(g_GroupHead->quantity<MAXGROUP)
{
g_GroupHead->cell[g_GroupHead->quantity]=temp;
g_GroupHead->quantity++;
}
/*
所存储的空闲块号大于MAXGROUP时需要另申请节点,因为每一组的空闲块数是MAXGROUP,
当大于这个MAXGROUP的时候,我们需要重新分配一个新组,这里我们用的是链表,相当于添加
一个新的节点,这个新节点p就是一个组里面又有MAXGROUP个空闲块。这样每一组都上以链表的
形式链接在一起的,组成一个链表,这也就是所谓的成组链接法。
*/
else
{
p=initial();
/*
p--
│
-->[head]---[a]----[b]---[c]--....
*/
p->next=g_GroupHead; //将申请的p节点插入到链首
g_GroupHead=p;
p->cell[p->quantity]=temp;
p->quantity++;
}
if (0 == g_UItotal++%10 )
{
cout << endl;
}
//输出初始数据
printf("%04d ",temp);
//cout<<temp<<" ";
}
cout<<endl<<"总空闲块数:"<<g_UItotal<<endl;
}
//查看专用块函数
void view()
{
int i;
cout<<endl<<"专用块数据如下:"<<endl;
cout<<"-------------------------------"<<endl;
cout<<"所存储的空闲块号:";
for(i=0;i<g_GroupHead->quantity;i++){
cout<<g_GroupHead->cell[i]<<" ";
}
cout<<endl<<"专用块空闲块数为:"<<g_GroupHead->quantity;
cout<<endl<<"总空闲块数:"<<g_UItotal<<endl;
}
//新申请函数
void bid()
{
char jobname[20];
UINT number;
UINT i;
job *p;
cout<<"----------------------------------"<<endl;
cout<<"请输入新作业名:";
cin>>jobname;
cout<<"所需内存块数:";
cin>>number;
if(number > g_UItotal)
{
cout<<"所需内存块数大于当前空闲块数,请稍候再试:)"<<endl;
}
else
{
p=initial_job();
strcpy(p->name,jobname);
/* 将节点p插入链表 */
p->next=g_JobHead->next;
g_JobHead->next=p;
p->quantity=number;
cout<<"申请成功,所申请到的空闲块号流:";
for(i=0;i<number;i++)
{
if(g_GroupHead->quantity > 1)
{
cout<<g_GroupHead->cell[g_GroupHead->quantity-1]<<" ";
g_GroupHead->quantity--;
p->cell[i]=g_GroupHead->cell[g_GroupHead->quantity-1];
}
else
{
cout<<g_GroupHead->cell[0]<<" ";
p->cell[i]=g_GroupHead->cell[g_GroupHead->quantity-1];
g_GroupHead->quantity--;
if(g_GroupHead->next!=NULL)
{
g_GroupHead=g_GroupHead->next;
}
}
g_UItotal--;
}
}
cout<<endl;
}
//撤消作业
void finish()
{
char jobname[20];
int i;
job *p,*q;
group *r;
cout<<"请输入要撤消的作业名:";
cin>>jobname;
q=g_JobHead;
p=g_JobHead->next;
while((p!=NULL)&&(strcmp(p->name,jobname))){
q=q->next;
p=p->next;
}
if(p==NULL)
{
cout<<"Sorry,没有该作业"<<endl;
}
else
{
for(i=0;i<p->quantity;i++)
{
if(g_GroupHead->quantity<MAXGROUP)
{
g_GroupHead->cell[g_GroupHead->quantity]=p->cell[i];
g_GroupHead->quantity++;
}
else{
r=initial();
r->next=g_GroupHead;
g_GroupHead=r;
r->cell[r->quantity]=p->cell[i];
r->quantity++;
}
}
g_UItotal+=p->quantity;
q->next=p->next;
delete p;
}
}
//显示版权信息函数
void version()
{
cout<<endl<<endl;
cout<<"┏━━━━━━━━━━━━━━━━━━━━━━━┓"<<endl;
cout<<"┃ 模拟UNIX的成组链接法 ┃"<<endl;
cout<<"┠───────────────────────┨"<<endl;
cout<<"┃ (c)All Right Reserved Neo ┃"<<endl;
cout<<"┃ zww0815@qq.com ┃"<<endl;
cout<<"┃ version 2011 build 1220 ┃"<<endl;
cout<<"┗━━━━━━━━━━━━━━━━━━━━━━━┛"<<endl;
cout<<endl<<endl;
}
void ShowHelp()
{
cout<<"===================================================="<<endl;
cout<<" 模拟UNIX的成组链接法 "<<endl;
cout<<"===================================================="<<endl;
cout<<"1.申请空闲块 2.撤消作业 3.查看专用块 0.退出"<<endl;
cout<<"请选择:";
}
//初始化全局化变量
void InitGlobalVariable()
{
//显示版本信息
version();
//初始化组链表
g_GroupHead=initial();
//初始化计数器
g_UItotal=0;
//初始化作业链表
g_JobHead=initial_job();
//从文件读取数据
readData();
}
int main()
{
UINT flag = 1;
UINT chioce = 0;
InitGlobalVariable();
while(flag == 1)
{
ShowHelp();
cin>>chioce;
switch(chioce){
case 1:
bid();
break;
case 2:
finish();
break;
case 3:
view();
break;
case 0:
flag = 0;
break;
default:
cout<<"选择错误!"<<endl;
}
}
return 0;
}
模拟UNIX系统文件管理成组连接算法(12.20更新中...)
最新推荐文章于 2023-04-22 15:21:08 发布