模拟UNIX系统文件管理成组连接算法(12.20更新中...)

14 篇文章 0 订阅
//[原创][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;
}

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实验二 UNIX磁盘空间管理算法 (一) 实验目的 掌握UNIX外存空间管理的分组链接算法。 (二) 实验内容 编写C语言程序,模拟UNIX磁盘空间管理使用的分组链接法。 1.定义一个记录磁盘号的堆栈S—free[10],以及记录栈现有磁盘数的变量S—nfree。 2.定义一个由40个元素构成的结构数组block[40]用作磁盘存放。 struct size { int blocl[10]; } struct blocd { struct size a[10]; //用于在空闲磁盘号链存放磁盘号 }block[40]; 3. 假设系统文件的最大容量为100个磁盘,且最多只有5个文件,定义一个由5个元素构成的结构数组file[5]用于记录各个文件占用的磁盘,。 struct File { int fileblocd[100]; //用于记录分别分配给文件的磁盘号 }file[5]; 4. 编写函数init( )完成空闲磁盘号堆栈、空闲磁盘号队列及记录文件占用磁盘状态的file结构数组。 5. 编写函数alloc(fileno,blockd),完成磁盘的分配操作。其的参数fileno为文件序号,用于指定需要分配的文件。 6. 编写函数free(fileno),完成文件占用磁盘的释放操作。其的参数fileno为文件序号,用于指定需要释放磁盘的文件。 7. 编写main( )函数完成下列操作: 调用init( )函数完成初始设置。 从终端输入命令,控制磁盘的分配与回收操作。 (三) 实验要求 1. 在程序运行的结果应包含磁盘的分配与回收操作。 2. 可根据输入的文件名、文件大小进行模拟磁盘分配,并在每次分配与回收后显示分配与回收是否成功,以及分配、回收的磁盘号。 3. 在程序执行过程,至少应包含分配不成功一次的信息。 4. 可以查看当前磁盘的使用情况:哪些空闲,哪些被哪些文件占用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值