网络工程专业 姓名:蔡利聪 学号:201306114117
一、目的和要求
1. 实验目的
连续内存分配方式会形成许多“碎片”,虽然可以通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无需再进行“紧凑”。基于这一思想而产生了离散分配方式。
如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。
在分页存储管理方式中,如果不具备页面兑换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具备支持虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。
本实验通过程序模拟操作系统的基本分页存储管理方式,进一步理解这一内存分配方式的原理和特点,加深对理论知识的掌握。
2.实验要求
(1)用C语言或Java语言编写程序模拟操作系统对内存的基本分页存储管理方式。
(2)程序要能正确对“内存”进行“分配”和“回收”,能接受用户的输入,显示内存的分配情况,并有一定的容错能力。
二、实验内容
本实验假定内存空间已经按块划分,目标程序无需关心内存块大小等底层细节,只需按算法对内存块进行分配即可。程序应该实现以下功能:
1、内存初始化。假定内存块共有N个,初始化后的内存空间应该有一部分已经被使用,这可以用随机数或程序内部的其他算法完成。
2、程序应该能接受用户输入的进程信息,并为之分配内存,返回分配结果(成功或失败),注意,此处应该考虑到不合法的输入并进行相应处理。
3、程序能回收用户指定的进程所占用的内存空间,因此,程序可能需要为每个进程分配一个唯一的进程号并给出详细的提示信息。
4、能直观合理地显示内存分配情况。
5、程序界面友好,便于操作和查看运行结果。
三、实验方法、步骤及结果测试
1. 源程序名:存储管理.cpp
可执行程序名:存储管理.exe
2. 原理分析
(1)编写该程序首先要定义一个一定空间大小的内存块100,即申请空闲区空间最大值,并且要初始化内存状态标志数组block[i],以及初始化存放进程的数组process[i][j],保证内存大小足够分配给相应的进程使用。
(2)通过设置菜单项,达到友好的访问内存的请求界面,把创建进程向内存获取空间,把结束进程让内存回收空间分为两个程序段函数,各自独立完成相应的功能,最后通过主函数直接调用创建进程和结束进程这两个函数。
3. 主要程序段及其解释:
1 #include <stdio.h> 2 #include <windows.h> 3 #define N 100 // 共有100个内存块 4 int process[N][N+1]; // 存放每个进程的页表 5 int block[N]; // 内存块状态标志数组,0:空闲,1:使用 6 int blockCount; // 记录当前内存剩余空间 7 int processCount; // 记录当前进程数 8 bool flag = true; 9 10 void init(); 11 void output(); 12 bool createProcess(); 13 bool endProcess(); 14 void menu(); 15 16 //主函数 17 void main() 18 { 19 init(); 20 menu(); 21 } 22 23 void init() 24 { 25 int i, j; 26 for (i=0; i<N; i++)// 初始化内存状态标志数组 27 block[i] = 0; 28 for (i=0; i<20; i++) 29 block[rand()%(N-1)] = 1; 30 blockCount = 0; 31 for (i=0; i<N; i++) 32 if (block[i] == 0) 33 blockCount++; 34 // 初始化存放进程的数组 35 for (i=0; i<N; i++) 36 { 37 process[i][0] = 0; 38 for (j=1; j<N; j++) 39 process[i][j] = -1; 40 } 41 processCount = 0; 42 printf("初始化结果如下:"); 43 output(); 44 flag = false; 45 } 46 void output() 47 { 48 printf(" 内存总量:%d 块, 已用空间:%d 块, 剩余空间:%d 块, 进程总数:%d 个 ", N, N-blockCount, blockCount, processCount); 49 if (flag && blockCount < N) 50 { 51 printf("已使用的内存块(%d): ", N-blockCount); 52 for (int k=0,count=0; k<N; k++) 53 { 54 if (block[k] == 1) 55 printf("%2d ", k, ++count); 56 57 if (count == 15) 58 { 59 putchar(' '); 60 count = 0; 61 } 62 } 63 putchar(' '); 64 } 65 // 输出各进程占用内存详细情况 66 if(processCount>0) 67 { 68 69 printf("内存详细使用情况如下: "); 70 for (int i=0; i<N; i++) 71 { 72 if (process[i][0] > 0) 73 { 74 printf("进程号:%d 占用内存块(%2d):", i, process[i][0]); 75 for (int j=1,count=0; j<=process[i][0]; j++) 76 { 77 printf("%2d ", process[i][j], count++); 78 if (count == 15) 79 { 80 putchar(' '); 81 printf(" "); 82 count = 0; 83 } 84 } 85 putchar(' '); 86 } 87 } 88 } 89 else 90 printf("当前内存无进程! "); 91 // 输出空闲内存块 92 putchar(' '); 93 } 94 bool createProcess() 95 { 96 int pid, pages, k = 0; 97 loop:printf("请输入进程号(小于%d)和所需页面数:", N); 98 scanf("%d%d", &pid, &pages); 99 if (pid > 99) 100 { 101 printf("错误!进程号过大! "); 102 goto loop; 103 } 104 if (pages > blockCount) 105 return false; 106 blockCount -= pages; 107 process[pid][0] = pages; 108 for (int i=1; i<=pages; i++) 109 { 110 while (block[k]==1 && k<100) 111 k++; 112 process[pid][i] = k; 113 block[k] = 1; 114 k++; 115 } 116 processCount++; 117 return true; 118 } 119 bool endProcess() 120 { 121 int pid, pages; 122 if (processCount < 1) 123 { 124 printf("当前内存没有进程! "); 125 return false; 126 } 127 printf("当前内存中的进程有 %d 个, 进程号为:", processCount); 128 for (int i=0; i<N; i++) 129 if (process[i][0] > 0) 130 printf("%2d ", i); 131 putchar(' '); 132 printf("请输入您要结束的进程号(小于%d):", N); 133 scanf("%d", &pid); 134 pages = process[pid][0]; 135 if (pages == 0) 136 { 137 printf("对不起!该进程不存在! "); 138 return false; 139 } 140 for (int j=1; j<pages; j++) 141 { 142 block[process[pid][j]] = 0; 143 process[pid][j] = -1; 144 } 145 process[pid][0] = 0; 146 processCount--; 147 blockCount += pages; 148 return true; 149 } 150 void menu() 151 { 152 int choice; 153 while (true) 154 { 155 printf("操作菜单: "); 156 printf(" 1 --> 创建进程 2 --> 结束进程 3 --> 查看内存 0 --> 退出程序 "); 157 printf("请输入您要进行的操作:"); 158 scanf("%d", &choice); 159 switch (choice) 160 { 161 case 1: 162 if (createProcess()) 163 printf("创建新进程成功! "); 164 else 165 printf("抱歉!内存空间不足,创建新进程失败! "); 166 break; 167 case 2: 168 if (endProcess()) 169 printf("进程已结束! "); 170 else 171 printf("进程结束失败! "); 172 break; 173 case 3: 174 output(); 175 break; 176 case 0: 177 return ; 178 default: 179 printf("对不起!您的选择有误!请重新选择! "); 180 } 181 } 182 }
4. 运行结果
默认创建的内存为100块,其中系统占用18块,剩余82块可供创建进程使用,当创建进程号为1,页面数为3的进程后,内存立刻为进程分配了3块空间0,1,2;当进程结束时,内存回收进程号1的空间,本次实验结果符合预期。
四、实验总结
本次实验是有关存储管理空间分配的算法的实现,实验内容相对之前的进程调度稍微简洁些,只需要通过内存空间大小,定义数组页表,然后进程请求空间块或释放空间块只需通过数组页表进行访问,然后内存提供相应的内存分配和回收。
虽然步骤比较清晰,对于二维数组使用的知识存在欠缺,写相关的代码比较不熟练,中间遇到很多困难,比如二维数组的调度,还有一些基本的C语言的语法结构掌握不熟练,而且对算法与与程序之间的思维不清晰,导致在写程序中出现较多问题,然后通过查找课本,上网搜寻资料,询问同学进行帮助解答,最后得到基本的实验程序。