Experimento de sistema operacional - alocação e liberação de memória principal (linguagem C)

Índice

Requisitos experimentais

Código

resultado da operação

Análise de código


Requisitos experimentais

1. Simule a alocação de memória principal do sistema operacional e use o algoritmo de gerenciamento de armazenamento de partições variáveis ​​para projetar o programa de alocação e reciclagem de memória principal sem realmente iniciar a operação de carregamento.

2. Adote o primeiro método de adaptação.

3. Quando um novo trabalho requer carregamento na memória principal, a tabela de áreas livres deve ser verificada para encontrar uma área livre grande o suficiente. Caso a área livre encontrada seja maior que a exigência do trabalho, ela deverá ser dividida em duas partes, sendo uma parte a área ocupada e a outra parte passa a ser área livre.

4. Quando um trabalho é evacuado, se a área devolvida for adjacente a outras áreas livres, ela deverá ser fundida em uma área livre maior e listada na tabela de áreas livres.

5. Execute o programa projetado e produza as alterações nos itens da tabela de estrutura de dados e o status atual da memória. 

Código

#include <stdio.h>
#define CAP 1024    //初始化内存容量 
#define SYSCAP 100  //系统所占地址,从低位开始 
#define N 1000		//进程最大个数 

//作业分区 
struct USED{
	int id,sp,ep,longsize;
}a[N];

//空闲分区 
struct FREE{
	int id,sp,ep,longsize;
}b[N];

//anum为作业分区块数,bnum为空闲分区块数。初始时作业分区0块,空闲分区有1块
int anum=0,bnum=1;        
void Init()              //初始化函数,程序开始时只有一个空闲分区 
{
	b[0].id=0;b[0].sp=SYSCAP;b[0].ep=CAP;b[0].longsize=b[0].ep-b[0].sp;
	printf("\n\n--------------最先适应算法--------------\n"); 
	printf("\n内存总量为:%dk\n",CAP); 
	printf("系统占用容量为:%dk\n",SYSCAP);
	printf("---------------------------------------------\n"); 
	printf("空闲分区    起始地址    结束地址    长度\n");
	printf("   %d          %d         %d       %d\n",b[0].id,b[0].sp,b[0].ep,b[0].longsize);
	printf("---------------------------------------------\n"); 
}
void Print(int anum,int bnum)      //格式化输出作业分区和空闲分区表 
{
	int i,j;
	printf("-----------------作业分区表---------------------\n"); 
	printf("作业分区    起始地址    结束地址    长度\n");
	for(i=0;i<anum;i++)
	{
		printf("   %d          %d         %d         %d\n",a[i].id,a[i].sp,a[i].ep,a[i].longsize);
	}
	printf("------------------空闲分区表--------------------\n"); 
	printf("空闲分区    起始地址    结束地址    长度\n");
	for(i=0;i<bnum;i++)
	{
		printf("   %d          %d         %d        %d\n",i,b[i].sp,b[i].ep,b[i].longsize);
	} 
	printf("---------------------------------------------\n\n\n"); 
}
void Put()                   //进程装入作业 
{
	int size;
	printf("请输入作业%d的大小\n",anum);
	scanf("%d",&size);
	int i;
	for(i=0;i<bnum;i++)
	{
		b[i].longsize=b[i].ep-b[i].sp;       //更新各空闲分区长度 
		if(b[i].longsize>=size)     //找到第一个能放下进程的空闲分区 
		{
			a[anum].id=anum;			//空闲区id 
			a[anum].sp=b[i].sp;			//作业内存起始地址等于空闲分区起始地址 
			a[anum].ep=a[anum].sp+size; //作业的结束地址等于起始地址+作业长度 
			b[i].sp=b[i].sp+size;		//空闲分区起始地址应向后移动size 
			a[anum].longsize=size;		//更新作业地址长度到结构体数组中 
			b[i].longsize=b[i].ep-b[i].sp;//更新空闲分区地址长度 
			anum++;						//作业数+1 
			break;						//一次只放入一个作业,结束查找 
		}
	}
	Print(anum,bnum);                   //打印结果 
}

void Merge()	//合并空闲分区,查找结束地址和开始地址重合的地址进行合并 
{
	int i,j;
	if(bnum>=1)   //当空闲分区大于等于两个时,才需要检查是否存在可合并的区间 
	{
		for(i=0;i<bnum-1;i++)//从第一个开始检查,到倒数第二个停止 
		{
			if(b[i].ep==b[i+1].sp)
			{
				bnum--;     //存在可合并区间,合并后空闲区间-1 
				b[i].ep=b[i+1].ep;  //结束地址变为合并后的结束地址 
				b[i].longsize=b[i].ep-b[i].sp;//更新空闲区间长度 
				for(j=i+1;i<bnum;i++)
				{
					b[j]=b[j+1];  //删除第i+1个空闲区间 
				}
			}
		}
	}
	
}

void Sort(int anum,int bnum)//简单排序函数,将空闲区间按起始地址递增的顺序排序 
{
	int i,j,min;
	for(i=0;i<bnum;i++)
	{
		min=b[i].sp;
		for(j=i;j<bnum;j++)
		{
			if(b[j].sp<min)
			{
				min=b[j].sp;
				b[N-1]=b[j];
				b[j]=b[i];
				b[i]=b[N-1];
			}
		}
	}
}

void Remove()//回收作业 
{
	int i,j,flag=1;//flag是标志位 
	printf("请输入需要回收的作业:\n");
	scanf("%d",&i);
	//回收作业存在下面两种情况 
	
	for(j=0;j<bnum;j++)//情况1:回收作业后,被回收作业地址刚好能和已存在的空闲分区合并,不需要增加空闲分区块数 
	{
		if(a[i].ep==b[j].sp)
		{
			b[j].sp=a[i].sp;   
			b[j].longsize=b[j].ep-b[j].sp;
			flag=0;  //标志位置0,只能执行一种情况 
			break;
		}
	}
	if(flag)		//情况2:回收作业后,被回收地址不能与已存在的空闲区间合并,需要增加空闲分区块数 
	{				//创建新的空闲分区 
		
		b[bnum].sp=a[i].sp;
		b[bnum].ep=a[i].ep;
		b[bnum].longsize=a[i].longsize;
		b[bnum].id=bnum;
		bnum++;		//空闲分区个数+1 
	}
	anum--;         //移除作业后,作业数-1 
	for(;i<anum;i++)
	{
		a[i]=a[i+1];//删除第i个作业分区 
		a[i].id--; //作业id对应-1 
	}
	Sort(anum,bnum);//排序 
	Merge();//再次检查合并空闲分区,防止出现增加空闲分区后出现的可合并分区 
	Print(anum,bnum);//打印结果 
}
int main()
{
	int input;//input 代表程序运行状态
	Init();//初始化,输出 
	while(1)//写一个死循环 
	{
		printf("装入作业:1  回收作业:0  其他输入结束程序\n");
		scanf("%d",&input);
		if(input==1)
		{
			Put();
		}else if(input==0)
		{
			Remove();
		}else break;//任意数字退出循环,程序结束 
	}
	return 0;
}

resultado da operação

 Análise de código

Defina a quantidade total de memória e memória do sistema como macros (se necessário, basta modificar diretamente os dados da definição da macro)

Defina duas matrizes de estrutura, respectivamente usadas para armazenar e liberar dados de status de partição

anum e bnum são variáveis ​​globais, representando o número de partições de trabalho e partições livres, respectivamente. 

#include <stdio.h>
#define CAP 1024    //初始化内存容量 
#define SYSCAP 100  //系统所占地址,从低位开始 
#define N 1000		//进程最大个数 
//作业分区 
struct USED{
	int id,sp,ep,longsize;
}a[N];
//空闲分区 
struct FREE{
	int id,sp,ep,longsize;
}b[N];
int anum=0,bnum=1;

  

 A função de inicialização imprime os dados iniciais antes que o programa de algoritmo inicie o processamento. Aqui o subscrito da matriz começa em 0

void Init()              //初始化函数,程序开始时只有一个空闲分区 
{
	b[0].id=0;b[0].sp=SYSCAP;b[0].ep=CAP;b[0].longsize=b[0].ep-b[0].sp;
	printf("\n\n--------------最先适应算法--------------\n"); 
	printf("\n内存总量为:%dk\n",CAP); 
	printf("系统占用容量为:%dk\n",SYSCAP);
	printf("---------------------------------------------\n"); 
	printf("空闲分区    起始地址    结束地址    长度\n");
	printf("   %d          %d         %d       %d\n",b[0].id,b[0].sp,b[0].ep,b[0].longsize);
	printf("---------------------------------------------\n"); 
}

Imprima os resultados e imprima os dados da estrutura correspondentes em ordem.

void Print(int anum,int bnum)      //格式化输出作业分区和空闲分区表 
{
	int i,j;
	printf("-----------------作业分区表---------------------\n"); 
	printf("作业分区    起始地址    结束地址    长度\n");
	for(i=0;i<anum;i++)
	{
		printf("   %d          %d         %d         %d\n",a[i].id,a[i].sp,a[i].ep,a[i].longsize);
	}
	printf("------------------空闲分区表--------------------\n"); 
	printf("空闲分区    起始地址    结束地址    长度\n");
	for(i=0;i<bnum;i++)
	{
		printf("   %d          %d         %d        %d\n",i,b[i].sp,b[i].ep,b[i].longsize);
	} 
	printf("---------------------------------------------\n\n\n"); 
}

 Algoritmo principal: carregue o trabalho na memória (os métodos de implementação específicos estão todos escritos nos comentários, se você ainda não entendeu, pode me enviar uma mensagem privada)

void Put()                   //进程装入作业 
{
	int size;
	printf("请输入作业%d的大小\n",anum);
	scanf("%d",&size);
	int i;
	for(i=0;i<bnum;i++)
	{
		b[i].longsize=b[i].ep-b[i].sp;       //更新各空闲分区长度 
		if(b[i].longsize>=size)     //找到第一个能放下进程的空闲分区 
		{
			a[anum].id=anum;			//空闲区id 
			a[anum].sp=b[i].sp;			//作业内存起始地址等于空闲分区起始地址 
			a[anum].ep=a[anum].sp+size; //作业的结束地址等于起始地址+作业长度 
			b[i].sp=b[i].sp+size;		//空闲分区起始地址应向后移动size 
			a[anum].longsize=size;		//更新作业地址长度到结构体数组中 
			b[i].longsize=b[i].ep-b[i].sp;//更新空闲分区地址长度 
			anum++;						//作业数+1 
			break;						//一次只放入一个作业,结束查找 
		}
	}
	Print(anum,bnum);                   //打印结果 
}

 Algoritmo principal: recicle o trabalho e recicle a memória ocupada pelo trabalho em uma área livre

 Vamos falar sobre por que existem duas situações em que as operações de reciclagem estão escritas no código

Caso 1:

Durante a reciclagem do trabalho, inserir a partição livre pode ser mesclada diretamente com a partição livre sem adicionar uma nova partição livre (conforme mostrado abaixo)

 Após reciclar e mesclar:

Caso 2:

Durante a reciclagem do trabalho, ao entrar na partição livre, ela não pode ser mesclada diretamente com a partição livre, e uma nova partição livre precisa ser adicionada (conforme mostrado na figura abaixo, o bloco amarelo é a partição do trabalho a ser reciclada)

Após reciclar e mesclar:

void Remove()//回收作业 
{
	int i,j,flag=1;//flag是标志位 
	printf("请输入需要回收的作业:\n");
	scanf("%d",&i);
	//回收作业存在下面两种情况 
	
	for(j=0;j<bnum;j++)//情况1:回收作业后,被回收作业地址刚好能和已存在的空闲分区合并,不需要增加空闲分区块数 
	{
		if(a[i].ep==b[j].sp)
		{
			b[j].sp=a[i].sp;   
			b[j].longsize=b[j].ep-b[j].sp;
			flag=0;  //标志位置0,只能执行一种情况 
			break;
		}
	}
	if(flag)		//情况2:回收作业后,被回收地址不能与已存在的空闲区间合并,需要增加空闲分区块数 
	{				//创建新的空闲分区 
		
		b[bnum].sp=a[i].sp;
		b[bnum].ep=a[i].ep;
		b[bnum].longsize=a[i].longsize;
		b[bnum].id=bnum;
		bnum++;		//空闲分区个数+1 
	}
	anum--;         //移除作业后,作业数-1 
	for(;i<anum;i++)
	{
		a[i]=a[i+1];//删除第i个作业分区 
		a[i].id--; //作业id对应-1 
	}
	Sort(anum,bnum);//排序 
	Merge();		//再次检查合并空闲分区,防止出现增加空闲分区后出现的可合并分区 
	Print(anum,bnum);//打印结果 
}

Algoritmo de classificação, reclassificando endereços de grandes para pequenos após cada reciclagem (esta etapa é obrigatória)

A reciclagem do trabalho é arbitrária. Se os blocos de endereços altos forem reciclados primeiro sem classificação, os endereços altos serão alocados primeiro na próxima vez que a partição livre for recuperada. Obviamente, isso não está de acordo com a definição do melhor algoritmo de adaptação.

void Sort(int anum,int bnum)//简单排序函数,将空闲区间按起始地址递增的顺序排序 
{
	int i,j,min;
	for(i=0;i<bnum;i++)
	{
		min=b[i].sp;
		for(j=i;j<bnum;j++)
		{
			if(b[j].sp<min)
			{
				min=b[j].sp;
				b[N-1]=b[j];
				b[j]=b[i];
				b[i]=b[N-1];
			}
		}
	}
}

 Função mesclar, verificar e depois mesclar. Esta é na verdade a terceira situação que ocorre após o processamento das duas situações anteriores.

 

Após reciclar e mesclar: 

void Merge()	//合并空闲分区,查找结束地址和开始地址重合的地址进行合并 
{
	int i,j;
	if(bnum>=1)   //当空闲分区大于等于两个时,才需要检查是否存在可合并的区间 
	{
		for(i=0;i<bnum-1;i++)//从第一个开始检查,到倒数第二个停止 
		{
			if(b[i].ep==b[i+1].sp)
			{
				bnum--;     //存在可合并区间,合并后空闲区间-1 
				b[i].ep=b[i+1].ep;  //结束地址变为合并后的结束地址 
				b[i].longsize=b[i].ep-b[i].sp;//更新空闲区间长度 
				for(j=i+1;i<bnum;i++)
				{
					b[j]=b[j+1];  //删除第i+1个空闲区间 
				}
			}
		}
	}
	
}

função principal. Chame a função de processamento correspondente por meio da entrada do usuário

int main()
{
	int input;//input 代表程序运行状态
	Init();//初始化,输出 
	while(1)//写一个死循环 
	{
		printf("装入作业:1  回收作业:0  其他输入结束程序\n");
		scanf("%d",&input);
		if(input==1)
		{
			Put();
		}else if(input==0)
		{
			Remove();
		}else break;//任意数字退出循环,程序结束 
	}
	return 0;
}

Obrigado pela leitura ~ Se você tiver alguma boa sugestão, pode comentar ou me enviar uma mensagem privada ~ Se não entender alguma coisa, também pode me enviar uma mensagem privada ~

Se você achar útil, por favor, dê um like e saia ~

Acho que você gosta

Origin blog.csdn.net/Lic_Ac/article/details/128021354
Recomendado
Clasificación