实验四主存空间的分配和回收
1. 目的和要求
1.1. 实验目的
用高级语言完成一个主存空间的分配和回收程序,以加深对动态分区分配方式及其算法的理解。
1.2. 实验要求
采用连续分配方式之动态分区分配存储管理,使用首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法4种算法完成设计。
(1)**设计一个作业申请队列以及作业完成后的释放顺序,实现主存的分配和回收。采用分区说明表进行。
(2)或在程序运行过程,由用户指定申请与释放。
(3)设计一个空闲区说明表,以保存某时刻主存空间占用情况。
把空闲区说明表的变化情况以及各作业的申请、释放情况显示。
2. 实验内容
根据指定的实验课题,完成设计、编码和调试工作,完成实验报告。
3. 实验环境
可以选用Visual C++作为开发环境。也可以选用Windows下的VB,CB或其他可视化环境,利用各种控件较为方便。自主选择实验环境。
4. 参考数据结构:
#include<stdio.h>
#include<conio.h>
#include<string.h>
#define MAX 24
struct partition{
char pn[10];
int begin;
int size;
int end; ////////
char status; //////////
};
typedef struct partition PART;
第一步:(第13周完成)
完成程序数据结构的创建,初始化内存分配情况,创建空闲分区表和已分配分区表
1 #include<stdio.h> 2 #include<conio.h> 3 #include<string.h> 4 #define MAX 24 5 #define Memory 512 6 struct partition{ 7 8 char pn[10]; 9 int begin; 10 int size; 11 int end; //////// 12 char status; ////////// 13 }; 14 typedef struct partition PART; 15 16 PART Free[MAX],Used[MAX],addresses[MAX]; 17 int sumFree,sumUsed,sumaddresses; 18 19 void addFree(int i,int j) 20 { 21 strcpy(addresses[i].pn,Free[j].pn); 22 addresses[i].begin=Free[j].begin; 23 addresses[i].size=Free[j].size; 24 addresses[i].status=Free[j].status; 25 } 26 27 void addUsed(int i,int j) 28 { 29 strcpy(addresses[i].pn,Used[j].pn); 30 addresses[i].begin=Used[j].begin; 31 addresses[i].size=Used[j].size; 32 addresses[i].status=Used[j].status; 33 } 34 35 void init()//初始化 36 { 37 38 sumFree=0,sumUsed=0,sumaddresses=0; 39 40 strcpy(Used[1].pn,"SYSTEM"); 41 Used[1].begin=0; 42 Used[1].size=100; 43 Used[1].status='u'; 44 sumUsed++; 45 46 sumaddresses++; 47 addUsed(sumaddresses,sumUsed); 48 49 50 printf("初始化,设内存总容量为512k "); 51 printf("系统从低地址部分开始使用,占用100k "); 52 53 54 55 strcpy(Free[1].pn,"----"); 56 Free[1].begin=100;//OS占用100K 57 Free[1].size=Memory-Free[1].begin; 58 Free[1].status='f'; 59 sumFree++; 60 61 sumaddresses++; 62 addFree(sumaddresses,sumFree); 63 } 64 65 66 void PT()//打印 67 { 68 int i; 69 printf("空闲区表Free "); 70 printf(" No. proname begin size status "); 71 for(i=1;i<=sumFree;i++) 72 printf(" No.%d %s %d %d %c ",i,Free[i].pn,Free[i].begin,Free[i].size,Free[i].status); 73 74 printf("已分配分区表Used "); 75 printf(" No. proname begin size status "); 76 for(i=1;i<=sumUsed;i++) 77 printf(" No.%d %s %d %d %c ",i,Used[i].pn,Used[i].begin,Used[i].size,Used[i].status); 78 79 printf("内存使用情况,按起始址增长的排: "); 80 printf(" No. proname begin size status "); 81 for(i=1;i<=sumaddresses;i++) 82 printf(" No.%d %s %d %d %c ",i,addresses[i].pn,addresses[i].begin,addresses[i].size,addresses[i].status); 83 } 84 85 int main() 86 { 87 init(); 88 PT(); 89 return 0; 90 }
第二步:(第14周完成)
完成为某作业分配内存空间。
- 用户输入作业名称;
- 判断作业名称是否已经存在,如果存在则要求用户重新输入;
- 用户输入作业所占空间大小;
- 判断是否能够在剩余的空闲区域中找到一块放置该作业,如果不行则要求用户重新输入;
- 显示菜单,由用户选择使用哪一种分配算法:
1) 首次适应算法
2) 循环首次适应算法
3) 最佳适应算法
4) 最坏适应算法
6.为该作业分配内存空间,分配处理流程图如下(size的值设定为1K):
7
- 屏幕显示分配后的内存分区情况
1 #include <stdio.h> 2 #include <conio.h> 3 #include <string.h> 4 #define MAX 512 5 6 struct partition { 7 char pn[10];//分区名字 8 int begin;//起始地址 9 int size;//分区大小 10 int end;//结束地址 11 char status;//分区状态 12 }; 13 struct partition part[MAX]; 14 int p = 0; //标记上次扫描结束处 15 16 void Init()//初始化分区地址、大小以及状态 17 { 18 int i; 19 for ( i = 0; i < MAX; i++ ) 20 part[i].status = '-'; 21 strcpy( part[0].pn, "SYSTEM" ); 22 part[0].begin = 0; 23 part[0].size = 100; 24 part[0].status = 'u'; 25 strcpy( part[1].pn, "-----" ); 26 part[1].begin = 100; 27 part[1].size = 412; 28 part[1].status = 'f'; 29 for ( i = 0; i < MAX; i++ ) 30 part[i].end = part[i].begin + part[i].size; 31 } 32 33 34 void Output( int i ) //以行的形式输出结构体的数据 35 { 36 printf( " %s", part[i].pn ); 37 printf( " %d", part[i].begin ); 38 printf( " %d", part[i].size ); 39 printf( " %d", part[i].end ); 40 printf( " %c", part[i].status ); 41 } 42 43 44 void Show() //显示分区 45 { 46 int i; 47 int n; //用n来记录分区的个数 48 printf( " ================================================================" ); 49 printf( " 已分配分区表Used:" ); 50 printf( " No. proname begin size end status" ); 51 printf( " ------------------------------------------------" ); 52 n = 1; 53 for ( i = 0; i < MAX; i++ ) 54 { 55 if ( part[i].status == '-' ) 56 break; 57 if ( part[i].status == 'u' ) 58 { 59 printf( " No.%d", n ); 60 Output( i ); 61 n++;// 记录已分配使用的分区个数 62 } 63 } 64 printf( " " ); 65 printf( " ================================================================" ); 66 printf( " 空闲分区表Free:" ); 67 printf( " No. proname begin size end status" ); 68 printf( " ------------------------------------------------" ); 69 n = 1; 70 for ( i = 0; i < MAX; i++ ) 71 { 72 if ( part[i].status == '-' ) 73 break; 74 if ( part[i].status == 'f' ) 75 { 76 printf( " No.%d", n ); 77 Output( i ); 78 n++; //记录空闲分区的个数 79 } 80 } 81 printf( " " ); 82 printf( " " ); 83 printf( " ================================================================" ); 84 printf( " 内存使用情况,按起始址增长的排:" ); 85 printf( " printf sorted by address:" ); 86 printf( " No. proname begin size end status" ); 87 printf( " ------------------------------------------------" ); 88 n = 1; 89 for ( i = 0; i < MAX; i++ ) 90 { 91 if ( part[i].status == '-' ) 92 break; 93 printf( " No.%d", n ); 94 Output( i ); 95 n++;//记录已分配分区以及空闲分区之和的总个数 96 } 97 getch(); 98 } 99 100 void Fit( int a, char workName[], int workSize ) //新作业把一个分区分配成两个分区:已使用分区和空闲分区 101 { 102 int i; 103 for ( i = MAX; i > a + 1; i-- ) 104 { 105 //通过逆向遍历,把在a地址后的所有分区往后退一个分区,目的在于增加一个分区 106 if ( part[i - 1].status == '-' ) 107 continue; 108 part[i]=part[i-1]; 109 } 110 strcpy( part[a + 1].pn, "-----" ); 111 part[a + 1].begin = part[a].begin + workSize; 112 part[a + 1].size = part[a].size - workSize; 113 part[a + 1].end = part[a].end; 114 part[a + 1].status = 'f'; 115 strcpy( part[a].pn, workName ); 116 part[a].size = workSize; 117 part[a].end = part[a].begin + part[a].size; 118 part[a].status = 'u'; 119 } 120 121 122 void Allocation() // 分配 123 { 124 int i; 125 int a; 126 int workSize; 127 char workName[10]; 128 int pFree; 129 printf( " 请输入作业名称:" ); 130 scanf( "%s", &workName ); 131 for(i=0;i<MAX;i++) 132 { 133 if(!strcmp(part[i].pn,workName))//判断作业名称是否已经存在 134 { 135 printf("该作业名称已经存在,请重新输入:" ); 136 return; 137 } 138 } 139 printf( "请输入作业大小(k):" ); 140 scanf( "%d", &workSize ); 141 for ( i = 0; i < MAX; i++ )//通过循环在空闲区找是否有适合区间存储作业 142 { 143 if ( part[i].status == 'f' && part[i].size >= workSize ) 144 { 145 pFree = i; 146 break; 147 } 148 } 149 if ( i == MAX ) 150 { 151 printf( " 该作业大小超出最大可分配空间,请重新输入:" ); 152 getch(); 153 return; 154 } 155 printf( " 请选择分配算法:" ); 156 printf( " 1、首次适应算法(FF)" ); 157 printf( " 2、循环首次适应算法(NF)" ); 158 printf( " 3、最佳适应算法(BF)" ); 159 printf( " 4、最坏适应算法(WF)" ); 160 printf( " 请输入选项:" ); 161 while ( 1 ) 162 { 163 scanf( "%d", &a ); 164 if ( a == 1 || a == 2 || a == 3 || a == 4 ) 165 break; 166 printf( "输入错误,请重新输入:" ); 167 } 168 switch ( a ) 169 { 170 case 1: 171 for ( i = 0; i < MAX; i++ )//首次适应算法(按地址从低到高查找) 172 if ( part[i].status == 'f' && part[i].size >= workSize ) 173 break; 174 Fit( i, workName, workSize ); 175 break; 176 case 2: 177 for ( p; p <= MAX; p++ )//循环首次适应算法 178 { 179 if ( p == MAX )//如果p指向地址末尾还没找到适合区间,则循环返回首地址0,继续寻找 180 p = 0; 181 if ( part[p].status == 'f' && part[p].size >= workSize ) 182 break; 183 } 184 Fit( p, workName, workSize ); 185 break; 186 case 3: 187 for ( i = 0; i < MAX; i++ )//最佳适应算法 188 if ( part[i].status == 'f' && part[i].size >= workSize ) 189 if ( part[pFree].size > part[i].size ) 190 pFree = i;//通过遍历所有区间,每次都找到最小空闲分区进行分配 191 Fit( pFree, workName, workSize ); 192 break; 193 case 4: 194 for ( i = 0; i < MAX; i++ )//最坏适应算法 195 if ( part[i].status == 'f' && part[i].size >= workSize ) 196 if ( part[pFree].size < part[i].size ) 197 pFree = i;//通过遍历所有区间,每次都找到最大空闲区分配 198 Fit( pFree, workName, workSize ); 199 break; 200 default: 201 break; 202 } 203 printf( " 分配成功!" ); 204 getch(); 205 } 206 207 208 void Merge() //合并连续的空闲分区 209 { 210 int i = 0; 211 while ( i != MAX - 1 ) 212 { 213 for ( i = 0; i < MAX - 1; i++ ) 214 { 215 if ( part[i].status == 'f' ) 216 if ( part[i + 1].status == 'f' ) 217 { 218 part[i].size = part[i].size + part[i + 1].size; 219 part[i].end = part[i].begin + part[i].size; 220 i++; 221 for ( i; i < MAX - 1; i++ ) 222 { 223 if ( part[i + 1].status == '-' ) 224 { 225 part[i].status = '-'; 226 break; 227 } 228 229 part[i]=part[i+1]; 230 } 231 part[MAX - 1].status = '-'; 232 break; 233 } 234 } 235 } 236 } 237 238 239 void Recovery() // 回收分区 240 { 241 int i; 242 int number; 243 int n=0; 244 printf( " 请输入回收的分区号:" ); 245 scanf( "%d", &number ); 246 if ( number == 1 ) 247 { 248 printf( " 系统分区无法回收" ); 249 return; 250 } 251 252 for ( i = 0; i < MAX; i++ )//通过循环查找要回收的已使用分区区号 253 { 254 if ( part[i].status == 'u' ) 255 { 256 n++; 257 if ( n == number ) 258 { 259 strcpy( part[i].pn, "-----" ); 260 part[i].status = 'f'; 261 } 262 } 263 } 264 if ( i == MAX - 1 ) 265 { 266 printf( " 找不到分区" ); 267 return; 268 } 269 Merge();//合并连续的空闲分区 270 printf( " 回收成功!" ); 271 getch(); 272 } 273 274 275 void main() 276 { 277 int selection; 278 Init(); 279 printf( "初始化,设内存容量%dk", MAX ); 280 printf( " 系统从低地址部分开始使用,占用%dk", part[0].size ); 281 printf(" "); 282 while ( 1 ) 283 { 284 printf( " " ); 285 printf( " 1、显示分区" ); 286 printf( " 2、分配作业" ); 287 printf( " 3、回收分区" ); 288 printf( " 请输入选项:" ); 289 while ( 1 ) 290 { 291 scanf( "%d", &selection ); 292 if ( selection == 0 ||selection == 1 || selection == 2 || selection == 3 ) 293 break; 294 printf( "输入错误,请重新输入:" ); 295 } 296 switch ( selection ) 297 { 298 case 1: 299 Show(); //显示分区 300 break; 301 case 2: 302 Allocation(); //分配作业 303 break; 304 case 3: 305 Recovery(); //回收分区 306 break; 307 default: 308 break; 309 } 310 } 311 }