Experimento 3: asignación y recuperación del espacio de memoria principal
1. El propósito del experimento
A través de este experimento, ayude a los estudiantes a comprender cómo realizar la asignación y recuperación del espacio de la memoria principal en el modo de administración de partición variable.
2. Contenido experimental
La memoria principal es la memoria donde la unidad central de procesamiento puede acceder directamente a instrucciones y datos. El hecho de que la memoria principal se pueda usar de manera razonable y efectiva afectará en gran medida el rendimiento de todo el sistema informático. Este experimento adopta la gestión de partición variable y utiliza el primer o mejor algoritmo de adaptación para realizar la asignación y recuperación del espacio de memoria principal. Es necesario utilizar la tabla de especificación de particiones.
Diseñe los procedimientos de recuperación y asignación de memoria principal de acuerdo con el primer (o mejor) algoritmo de ajuste. Utilizando la Figura 1 como base para el uso actual de la memoria principal, inicialice los valores de las tablas de descripción del área libre y del área asignada. Los estudiantes diseñan una cola de solicitud de trabajo y la secuencia de liberación después de completar el trabajo para realizar la asignación y recuperación de la memoria principal. Muestre o imprima los cambios de la tabla de descripción del área libre y el estado de solicitud y liberación de cada trabajo.
3. Análisis de código y ejecución de resultados
(3) El código fuente del programa es el siguiente:
#include <stdio.h>
#include <string.h>
#define MAX 600 //设置总内存大小为512k
struct partition {
char pn[10];//分区名字
int begin;//起始地址
int size;//分区大小
int end;//结束地址
char status;//分区状态
};
struct partition part[MAX];
int p = 0; //标记上次扫描结束处
void Init()//初始化分区地址、大小以及状态
{
int i;
for ( i = 0; i < MAX; i++ )
part[i].status = '-';
strcpy( part[0].pn, "SYSTEM" );
part[0].begin = 0;
part[0].size = 100;
part[0].status = 'u';
strcpy( part[1].pn, "-----" );
part[1].begin = 100;
part[1].size = 100;
part[1].status = 'f';
strcpy( part[2].pn, "作业1" );
part[2].begin = 200;
part[2].size = 50;
part[2].status = 'u';
strcpy( part[3].pn, "-----" );
part[3].begin = 250;
part[3].size = 50;
part[3].status = 'f';
strcpy( part[4].pn, "作业2" );
part[4].begin = 300;
part[4].size = 100;
part[4].status = 'u';
strcpy( part[5].pn, "-----" );
part[5].begin = 400;
part[5].size = 200;
part[5].status = 'f';
for ( i = 0; i < MAX; i++ )
part[i].end = part[i].begin + part[i].size-1;
}
void Output( int i ) //以行的形式输出结构体的数据
{
printf( "\t%s", part[i].pn );
printf( "\t%d", part[i].begin );
printf( "\t%d", part[i].size );
printf( "\t%d", part[i].end );
printf( "\t%c", part[i].status );
}
void display() //显示分区
{
int i;
int n; //用n来记录分区的个数
printf("\n");
printf( "\n 已分配分区表Used:" );
printf( "\n\tNo.\tproname\tbegin\tsize\tend\tstatus" );
printf("\n");
n = 1;
for ( i = 0; i < MAX; i++ )
{
if ( part[i].status == '-' )
break;
if ( part[i].status == 'u' )
{
printf( "\n\tNo.%d", n );
Output( i );
n++;// 记录已分配使用的分区个数
}
}
printf("\n");
printf( "\n 空闲分区表Free:" );
printf( "\n\tNo.\tproname\tbegin\tsize\tend\tstatus" );
printf("\n");
n = 1;
for ( i = 0; i < MAX; i++ )
{
if ( part[i].status == '-' )
break;
if ( part[i].status == 'f' )
{
printf( "\n\tNo.%d", n );
Output( i );
n++; //记录空闲分区的个数
}
}
printf("\n");
printf( "\n 内存使用情况,按起始址增长的排:" );
//printf( "\n printf sorted by address:" );
printf( "\n\tNo.\tproname\tbegin\tsize\tend\tstatus" );
printf("\n");
n = 1;
for ( i = 0; i < MAX; i++ )
{
if ( part[i].status == '-' )
break;
printf( "\n\tNo.%d", n );
Output( i );
n++;//记录已分配分区以及空闲分区之和的总个数
}
}
void Fit( int a, char workName[], int workSize ) //新作业把一个分区分配成两个分区:已使用分区和空闲分区
{
int i;
for ( i = MAX; i > a + 1; i-- ){
//通过逆向遍历,把在a地址后的所有分区往后退一个分区,目的在于增加一个分区
if ( part[i - 1].status == '-' )
continue;
part[i]=part[i-1];
}
strcpy( part[a + 1].pn, "-----" );
part[a + 1].begin = part[a].begin + workSize;
part[a + 1].size = part[a].size - workSize;
part[a + 1].end = part[a].end-1;
part[a + 1].status = 'f';
strcpy( part[a].pn, workName );
part[a].size = workSize;
part[a].end = part[a].begin + part[a].size-1;
part[a].status = 'u';
}
void fenpei() // 分配
{
int i;
int a;
int workSize;
char workName[10];
int pFree;
printf( "\n请输入作业名称:" );
scanf( "%s", &workName );
for(i=0;i<MAX;i++){
if(!strcmp(part[i].pn,workName))//判断作业名称是否已经存在
{
printf("\n作业已经存在,不必再次分配!\n");
return;
}
}
printf( "请输入作业大小(k):" );
scanf( "%d", &workSize );
for ( i = 0; i < MAX; i++ ){
//通过循环在空闲区找是否有适合区间存储作业
if ( part[i].status == 'f' && part[i].size >= workSize ){
pFree = i;
break;
}
}
if ( i == MAX ){
printf( "\n该作业大小超出最大可分配空间" );
getch();
return;
}
for ( i = 0; i < MAX; i++ )//最佳适应算法
if ( part[i].status == 'f' && part[i].size >= workSize )
if ( part[pFree].size > part[i].size )
pFree = i;//通过遍历所有区间,每次都找到最小空闲分区进行分配
Fit( pFree, workName, workSize );
printf( "\n分配成功!" );
}
void hebing() //合并连续的空闲分区
{
int i = 0;
while ( i != MAX - 1 ){
for ( i = 0; i < MAX - 1; i++ ){
if ( part[i].status == 'f' )
if ( part[i + 1].status == 'f' ){
part[i].size = part[i].size + part[i + 1].size;
part[i].end = part[i].begin + part[i].size-1;
i++;
for ( i; i < MAX - 1; i++ ){
if ( part[i + 1].status == '-' ){
part[i].status = '-';
break;
}
part[i]=part[i+1];
}
part[MAX - 1].status = '-';
break;
}
}
}
}
void huishou() // 回收分区
{
int i;
int number;
int n=0;
printf( "\n请输入回收的分区号:" );
scanf( "%d", &number );
if ( number == 1 )
{
printf( "\n系统分区无法回收" );
return;
}
for ( i = 0; i < MAX; i++ )//通过循环查找要回收的已使用分区区号
{
if ( part[i].status == 'u' )
{
n++;
if ( n == number )
{
strcpy( part[i].pn, "-----" );
part[i].status = 'f';
}
}
}
if ( i == MAX - 1 )
{
printf( "\n找不到分区" );
return;
}
hebing();//合并连续的空闲分区
printf( "\n回收成功!" );
}
void main()
{
int selection;
Init();
printf( "初始化完成,设内存容量%dk", MAX );
printf( "\n系统文件从低址存储,占%dk", part[0].size );
while ( 1 ){
printf( "\n----------选择----------" );
printf( "\n| 0、退出系统 |" );
printf( "\n| 1、显示分区 |" );
printf( "\n| 2、分配分区 |" );
printf( "\n| 3、回收分区 |" );
printf( "\n------------------------");
printf( "\n请选择 > " );
while ( 1 )
{
scanf( "%d", &selection );
if ( selection == 0 ||selection == 1 || selection == 2 || selection == 3 )
break;
printf( "输入错误,请重新输入:" );
}
switch ( selection ){
case 0:
exit(0); //退出系统
break;
case 1:
display(); //显示分区
break;
case 2:
fenpei(); //分配作业
break;
case 3:
huishou(); //回收分区
break;
default:
break;
}
printf("\n");
}
}
(4) Los resultados de la operación se muestran en la siguiente figura:
1) Utilizando la Figura 1 como base para el uso actual de la memoria principal, inicialice los valores del área libre y la tabla de descripción del área asignada para prepararse para la verificación. del mejor algoritmo de adaptación:
2) Para el trabajo a1, a2, a3, asigne memoria para prepararse para verificar el mejor algoritmo de adaptación:
3) Recupere la memoria de a2 para prepararse para verificar el mejor algoritmo de adaptación:
4) Verificar la asignación de memoria del algoritmo de mejor ajuste, asignada para el trabajo d. Debido a que el algoritmo de mejor ajuste encuentra la partición libre más pequeña que puede cumplir con los requisitos del trabajo de todas las áreas libres, los resultados son los siguientes y la verificación es correcta:
5) Verifique la recuperación de memoria del algoritmo de mejor ajuste. la partición libre F1 es adyacente. En este momento, el área reclamada debe fusionarse con la partición anterior del punto de inserción. No es necesario asignar una nueva entrada para la partición reclamada, sino solo modificar el tamaño de su partición anterior F1 :
6) Verifique la recuperación de memoria del mejor algoritmo de adaptación. Cuando el área de recuperación se encuentra junto a la siguiente partición libre F2 del punto de inserción, las dos particiones también se pueden fusionar para formar una nueva partición libre, pero la primera dirección de la recuperación El área se utiliza como la nueva partición libre. La primera dirección del área libre, el tamaño es la suma de los dos:
7) Verifique la recuperación de memoria del mejor algoritmo de adaptación.Cuando el área de recuperación es adyacente a las dos particiones F1 y F2 antes y después del punto de inserción al mismo tiempo, las tres particiones se fusionan en este momento, y la entrada de la tabla de F1 y la primera dirección de F2 se utilizan para cancelar F2. , cuyo tamaño es la suma de los tres.
8) Verifique la recuperación de memoria del algoritmo de mejor ajuste, cuando el área de recuperación no sea adyacente a F1 ni a F2. En este momento, se debe crear una nueva entrada para el área de reciclaje, completar la primera dirección y el tamaño del área de reciclaje e insertarla en la posición adecuada en la cadena libre según su primera dirección.