Experimento del sistema operativo: asignación y liberación de memoria principal (lenguaje C)

Tabla de contenido

Requisitos experimentales

Código

resultado de la operación

Análisis de código


Requisitos experimentales

1. Simule la asignación de memoria principal del sistema operativo y utilice el algoritmo de administración de almacenamiento de particiones variables para diseñar el programa de reciclaje y asignación de memoria principal sin iniciar realmente la operación de carga.

2. Adoptar el método del primero en adaptar.

3. Cuando es necesario cargar un nuevo trabajo en la memoria principal, se debe verificar la tabla de áreas libres para encontrar un área libre lo suficientemente grande. Si el área libre encontrada es mayor que el requerimiento del trabajo, se debe dividir en dos partes, una parte es el área ocupada y la otra parte se convierte en un área libre.

4. Cuando se evacua un trabajo, si el área devuelta es adyacente a otras áreas libres, se debe fusionar en un área libre más grande y enumerarla en la tabla de áreas libres.

5. Ejecute el programa diseñado y genere los cambios en los elementos de la tabla de estructura de datos y el estado actual de la memoria. 

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 de la operación

 Análisis de código

Defina la cantidad total de memoria y la memoria del sistema como macros (si es necesario, simplemente modifique los datos de la definición de macro directamente)

Defina dos matrices de estructura, utilizadas respectivamente para almacenar y liberar datos de estado de partición

anum y bnum son variables globales que representan el número de particiones de trabajo y particiones libres 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;

  

 La función de inicialización imprime los datos iniciales antes de que el programa del algoritmo comience a procesar. Aquí el subíndice de la matriz comienza desde 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 los resultados e imprima los datos de la estructura correspondiente en orden.

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 central: cargue el trabajo en la memoria (todos los métodos de implementación específicos están escritos en los comentarios, si aún no lo comprende, puede enviarme un mensaje privado)

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 central: recicle el trabajo y recicle la memoria ocupada por el trabajo en un área libre

 Hablemos de por qué hay dos situaciones al reciclar operaciones escritas en el código.

Caso 1:

Durante el reciclaje del trabajo, ingresar a la partición libre se puede fusionar directamente con la partición libre sin agregar una nueva partición libre (como se muestra a continuación)

 Después de reciclar y fusionar:

Caso 2:

Durante el reciclaje del trabajo, al ingresar a la partición libre, no se puede fusionar directamente con la partición libre y es necesario agregar una nueva partición libre (como se muestra en la figura siguiente, el bloque amarillo es la partición del trabajo que se reciclará)

Después de reciclar y fusionar:

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 clasificación, reordenación de direcciones de mayor a menor después de cada reciclaje (este paso es obligatorio)

El reciclaje de trabajos es arbitrario. Si los bloques de direcciones altas se reciclan primero sin ordenar, las direcciones altas se asignarán primero cuando se recupere la partición libre la próxima vez. Obviamente, esto no cumple con la definición del mejor algoritmo de adaptación.

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];
			}
		}
	}
}

 Fusionar función, verificar y luego fusionar Esta es en realidad la tercera situación que ocurre después de procesar las dos situaciones anteriores.

 

Después de reciclar y fusionar: 

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个空闲区间 
				}
			}
		}
	}
	
}

función principal. Llame a la función de procesamiento correspondiente a través de la entrada del usuario

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;
}

Gracias por leer ~ Si tienes alguna buena sugerencia, puedes comentar o enviarme un mensaje privado ~ Si no entiendes algo, también puedes enviarme un mensaje privado ~

Si lo encuentras útil, dale me gusta y vete ~

Supongo que te gusta

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