www.pudn.com > DynamicMemoryManage.rar > memory.cpp
///实验 :动态分区存储管理方式的主存分配回收 /*实验内容:编写程序完成动态分区存储管理方式的主存分配回收的实现。*/ //////////实验具体包括:首先确定主存空间分配表;然后采用最优适应 /////////算法完成主存空间的分配,完成主存空间的回收;最后编写主函数对所作工作进程测试。 #include#include #define FREE 10 //假定系统允许的空闲区表最大为FREE #define TASK 10 //假定系统允许的最大作业数量为TASK #define MINSIZE 1000 //分区最小字节数,小于该值的区域为碎片 typedef struct used { float address; //已分分区起始地址 float length; //已分分区长度 int flag; //已分配区表登记栏标志,0表示空栏目,实验中只支持数字作业名 }USED_TABLE; //已分配区表结构 typedef struct free { float address; //空闲区起始地址 float length; //空闲区长度 int flag; //空闲区表登记栏标志,0表示空栏目,1表示未分配 }FREE_TABLE; //空闲区表结构 typedef struct task { int pId; //任务标识 float length; //任务所需长度 }sTASK; //任务结构 USED_TABLE used_table[TASK]; //已分配分区表 FREE_TABLE free_table[FREE]; //空闲区表 //分配函数////////////////////////////////////////// int assign(int pId, float pLength) { int n; for( n=0; n = pLength)) { //如果i区是未分配的且满足作业要求 if(best == -1) { //如果i是第一个未分配的 best = i; //则记i为当前查找到的最符合作业要求的空闲区 } else if(free_table[i].length < free_table[best].length) { //或i空闲区的长度小于best空闲区的长度 best = i; //则记i为当前查找到的最符合作业要求的空闲区 } } } //查找完毕 //未找到满足需求的分区 if(best == -1) //如果未找到满足需求的分区 { printf("主存分配失败\n"); //打印错误信息 return -1; //退出 } //找到满足需求的分区,开始主存分配 if((free_table[best].length - pLength) <= MINSIZE) //如果best的长度-作业需求长度 小于 MINSIZE { //分配给作业整个分区 free_table[best].flag = 0; //状态置为空 address = free_table[best].address; //记录下best的地址 pLength = free_table[best].length; //记录下best的长度 } else { //切割空闲区 free_table[best].length = free_table[best].length - pLength; //best栏的长度减去作业要求的长度 address = free_table[best].address + free_table[best].length; //记录下分配给作业的主存地址 } int j = 0; //访问已分配区表的指针 while(j < TASK) //第j栏属于已分配表的栏 { if(used_table[j].flag == 0) //如果第j栏为空 break; //则跳出 j++; //指针后移 } if(j < TASK) //如果第j栏是已分配表中的一栏 { //填写已分配区表 used_table[j].address = address; //填写地址 used_table[j].length = pLength; //填写长度 used_table[j].flag = pId; //填写作业名 return 1; //成功 } else //第j栏不是已分配表中的一栏 { if(free_table[best].flag == 0) //best为空 { printf("主存未分配\n"); //打印分配失败 } else //best不为空 { free_table[best].length += pLength; //恢复best的原长度 } printf("已分配区表长度不足,分配失败\n"); //打印分配失败信息 return -1; //失败 } } //分配函数结束///////////////////////////////////// //回收函数////////////////////////////////////////// int recycle(int pId) { ///回收作业pId的内存空间 int rId; //标识要回收的作业号对应的在已分配表中的序号 rId = 0; //赋初值为0 while(rId < TASK) //当rId为已分配区表中的一栏 { if(used_table[rId].flag == pId) //当找到要回收的作业号对应的在已分配表中的序号 break; //跳出循环 rId++; //指针后移 } if(rId >= TASK) //如果rId不是已分配区表中的一栏,则 { printf("未找到作业%d,回收失败\n", pId); //未找到作业 return -1; //退出 } //rId是已分配区表中的一栏,开始回收 int up = -1; //上邻空闲区序号 int down = -1; //下邻空闲区序号 float rAddress; //记录已分配区表中第rId栏的起始地址 float rLength; //记录已分配区表中第rId栏的长度 rAddress = used_table[rId].address; //记录已分配区表中第rId栏的起始地址 rLength = used_table[rId].length; //记录已分配区表中第rId栏的长度 used_table[rId].flag = 0; //变为空栏 for(int i = 0; i < FREE; i++) { //第i栏是空闲区表中的一栏或回收的上邻和下邻未找完 if(free_table[i].flag == 0) //如果第i栏为未分配,则 continue; //继续下一次循环,终止以下的工作 if((free_table[i].address + free_table[i].length) == rAddress) //如果第i栏是回收区的上邻 up = i; //记录下上邻号 else if(free_table[i].address == (rAddress + rLength)) //如果第i栏是回收区的下邻 down = i; //记录下下邻号 if((up != -1) && (down != -1)) //如果找到了上邻和下邻 break; //跳出循环 } if(up != -1) //回收区有上邻 { if(down != -1) //回收区有下邻 { free_table[up].length += free_table[down].length + rLength; //修改上邻的长度 free_table[down].flag = 0; //下邻置为空 free_table[down].address = -1; //置其地址为无效 free_table[down].length = 0; //长度为0 } else //没有下邻 { free_table[up].length += rLength; //修改上邻长度 } } else //没有上邻 { if(down != -1) //有下邻 { free_table[down].length += rLength; //下邻长度加上回收的长度 free_table[down].address = rAddress; //下邻地址改为回收区的地址 } else //没有下邻 { int t = 0; //访问指针 for(t = 0; t < FREE; t++) //寻找一个未分配的栏 { if(free_table[t].flag == 0) //找到一个为空的栏 break; //跳出循环 } if(t < FREE) //第t栏是空闲区表中的一栏 { //归还分区填入空闲区表 free_table[t].address = rAddress; //填写地址 free_table[t].length = rLength; //填写长度 free_table[t].flag = 1; //未分配 } else { used_table[rId].flag = pId; //恢复已分配区表要回收的作业号 printf("空闲区长度不足,回收失败\n"); //打印错误信息 return -1; } } } return 1; //返回成功 } //回收函数结束////////////////////////////////////// //初始化函数//////////////////////////////////////// void initial() { ///初始化已分配区表和空闲区表 //初始化已分配区表 for(int i = 0; i < TASK; i++) { used_table[i].address = -1; //初始化为无效地址 used_table[i].flag = 0; //初始化为空 used_table[i].length = 0; //初始化长度为0 } //初始化空闲区表,初始主存为一个大的空闲块 free_table[0].address = 0; //初始地址从0开始 free_table[0].length = 100000; //设空闲区大小为100k free_table[0].flag = 1; //初始为未分配 for(int j = 1; j < FREE; j++) //将其余栏初始为空 { free_table[j].address = -1; //初始化为无效地址 free_table[j].length = 0; //长度为0 free_table[j].flag = 0; //初始化主存为空 } } //初始化函数结束/////////////////////////////////// //从文件导入任务队列创建 函数//////////////////////////// int importToCreate(char *file, char *sFile) { FILE *fp, *sFp; //文件指针 if((fp = fopen(file, "rb")) == NULL) //打开文件(只读) { printf("文件打开错误\n"); //打印错误信息 return -1; //退出 } if((sFp = fopen(sFile, "a")) == NULL) //打开文件(追加) { printf("文件打开错误\n"); //打印错误信息 return -1; //退出 } sTASK task; //任务,保存从文件读出的任务 int suc; //标识是否成功 while(!feof(fp)) //文件不到结尾则继续 { fscanf(fp, "%d, %f", &task.pId, &task.length); //从文件中读出一条任务 suc = assign(task.pId, task.length); //分配主存 if(suc == 1) //成功分配 { fprintf(sFp, "成功为作业%d 分配主存\n", task.pId); //写入文件 printf("成功为作业%d 分配主存\n", task.pId); //打印信息 } else { fprintf(sFp, "为作业%d 分配主存失败\n", task.pId); //写入文件 } // //写表状态信息到文件sFile char line[] = "----------------------------------------------------"; //分隔线 char header1[] = "任务:\npId address length"; //表头1 char header2[] = "主存:\naddress length flag"; //表头2 fprintf(sFp, "%s\n", line); //写入分隔线 fprintf(sFp, "%s\n", header1); //写表头1 for(int i = 0; i < TASK; i++) { ///遍历所有已分配区表栏 if(used_table[i].flag != 0) //如果该栏有任务 { //打印该栏数据 fprintf(sFp, "%2d%9.0f%12.0f\n", used_table[i].flag,used_table[i].address,used_table[i].length); } } fprintf(sFp, "\n%s\n", header2); //打印表头2 for(int j = 0; j < FREE; j++) //打印所有空闲区表内容 { //内容 fprintf(sFp, "%3.0f%12.0f%5d\n",free_table[j].address,free_table[j].length,free_table[j].flag); } fprintf(sFp, "%s\n", line); //写入分隔线 //////////////////////////////////// } fclose(sFp); //关闭文件sFp fclose(fp); //关闭文件fp return 1; //返回成功 } //导入创建 函数结束//////////////////////////// //导入回收 函数///////////////////////////////// int importToRecycle(char *file, char *sFile) { FILE *fp, *sFp; //文件指针 if((fp = fopen(file, "rb")) == NULL) //打开文件(只读) { printf("文件打开错误\n"); //打印错误信息 return -1; //退出 } if((sFp = fopen(sFile, "a")) == NULL) //打开文件(追加) { printf("文件打开错误\n"); //打印错误信息 return -1; //退出 } //开始读文件并回收 int suc; //标识是否成功 int pId; //记录读出的任务标识 while(!feof(fp)) //文件不到结尾则继续 { fscanf(fp, "%d", &pId); //从文件中读出一条记录 suc = recycle(pId); //回收 if(suc == 1) //回收成功 { fprintf(sFp, "回收作业%d 空间成功\n", pId); //写入文件 printf("成功回收任务%d 的空间\n", pId); //提示信息 } else //回收失败 { fprintf(sFp, "回收作业%d 空间失败\n", pId); //写入文件 } //写表状态到文件 char line[] = "----------------------------------------------------"; //分隔线 char header1[] = "任务:\npId address length"; //表头1 char header2[] = "主存:\naddress length flag"; //表头2 fprintf(sFp, "%s\n", line); //写入分隔线 fprintf(sFp, "%s\n", header1); //写表头1 for(int i = 0; i < TASK; i++) { ///遍历所有已分配区表栏 if(used_table[i].flag != 0) //如果该栏有任务 { //打印该栏数据 fprintf(sFp, "%2d%9.0f%12.0f\n", used_table[i].flag,used_table[i].address,used_table[i].length); } } fprintf(sFp, "\n%s\n", header2); //打印表头2 for(int j = 0; j < FREE; j++) //打印所有空闲区表内容 { //内容 fprintf(sFp, "%3.0f%12.0f%5d\n",free_table[j].address,free_table[j].length,free_table[j].flag); } fprintf(sFp, "%s\n", line); //写入分隔线 ////////////////////////////////////////////// } fclose(sFp); //关闭文件sFp fclose(fp); //关闭文件fp return 1; //成功完成 } //导入回收函数结束///////////////////////////// //保存当前状态到文件函数/////////////////////////// int saveToFile(char *file) { FILE *fp; //文件指针 if((fp = fopen(file, "a")) == NULL) //打开文件(追加) { printf("文件打开错误\n"); //打印错误信息 return -1; //退出 } char line[] = "----------------------------------------------------"; //分隔线 char header1[] = "任务:\npId address length"; //表头1 char header2[] = "主存:\naddress length flag"; //表头2 fprintf(fp, "%s\n", line); //写入分隔线 fprintf(fp, "%s\n", header1); //写表头1 for(int i = 0; i < TASK; i++) { ///遍历所有已分配区表栏 if(used_table[i].flag != 0) //如果该栏有任务 { //打印该栏数据 fprintf(fp, "%2d%9.0f%12.0f\n", used_table[i].flag,used_table[i].address,used_table[i].length); } } fprintf(fp, "\n%s\n", header2); //打印表头2 for(int j = 0; j < FREE; j++) //打印所有空闲区表内容 { //内容 fprintf(fp, "%3.0f%12.0f%5d\n",free_table[j].address,free_table[j].length,free_table[j].flag); } fprintf(fp, "%s\n", line); //写入分隔线 fclose(fp); return 1; //返回成功 } //保存当前状态到文件 函数结束/////////////////////// //打印内存使用情况//////////////////////////////// void prtMem() { printf("----------------------------------------------------\n"); //分隔线 printf("任务:\npId address length\n"); //打印标题 for(int i = 0; i < TASK; i++) { ///遍历所有已分配区表栏 if(used_table[i].flag != 0) //如果该栏有任务 { //打印该栏数据 printf("%2d%9.0f%12.0f\n", used_table[i].flag,used_table[i].address,used_table[i].length); } } printf("\n"); //打印一个空行 printf("主存:\naddress length flag\n"); //打印标题 for(int j = 0; j < FREE; j++) //打印所有空闲区表内容 { //内容 printf("%3.0f%12.0f%5d\n",free_table[j].address,free_table[j].length,free_table[j].flag); } printf("----------------------------------------------------\n"); //分隔线 } //打印结束//////////////////////////////////////// //打印菜单函数//////////////////////////////////// void menu() { //打印菜单 printf("\t1: 创建"); //选项1 printf("\t2: 回收"); //选项2 printf("\t3: 用文件导入创建或者导入回收"); //选项3 printf("\t4: 退出\n"); //选项4 printf("请选择:"); //提示选择 } void menu1() { printf("\t1: 导入任务并创建\n"); //选项3 printf("\t2: 导入任务并回收\n");//选项4 printf("\t3: 退回上一级菜单\n");//选项5 printf("请选择:"); } //打印菜单函数结束/////////////////////////////// //main///////////////////////////////////////////// void main() { ///初始化 initial(); int c; //选择指针 printf(" 实验二 动态分区存储管理方式的主存分配回收 \n"); //打印标题 hello: menu(); //打印菜单 scanf("%d", &c);//输入选择 while(c != 4) //没选择退出,则继续 { if(c == 1) { //创建任务,为之分配主存空间 int p; //任务标识 float m; //任务所需主存空间 printf("输入任务ID: "); //提示输入任务标识 scanf("%d", &p); //输入任务标识 printf("输入占用的主存空间: ", p); //提示输入其所需主存空间 scanf("%f", &m); //输入其所需主存空间 assign(p, m); //为任务p分配其所需主存空间 prtMem(); //打印当前已分配区表和空闲区表状态 } else if(c == 2) { //回收主存空间 int pi; //任务标识 printf("输入要回收的任务ID: "); //提示输入任务标识 scanf("%d", &pi); //输入任务标识 recycle(pi); //回收任务pi的主存空间 prtMem(); //打印当前已分配区表和空闲区表状态 } else if(c == 3) { int choose;//选择选项 menu1(); scanf("%d",&choose); if(choose ==3) {goto hello;} while(choose !=3) { if (choose == 1) //从文件导入任务队列创建 { int suc; //标识是否成功创建 char *fileName; //文件名 char *sFileName; //保存表状态的文件名 fileName = (char *)malloc(10); //为fileName分配内存 sFileName = (char *)malloc(10); //为sFileName分配内存 printf("输入任务列表文件名: "); //提示输入文件名 scanf("%s", fileName); //输入文件名 printf("输入保存表状态的文件名:"); //提示输入文件名 scanf("%s", sFileName); //输入文件名 suc = importToCreate(fileName, sFileName); //从文件导入任务并分配主存 if(suc == 1) //成功创建 printf("已成功完成分配任务\n"); //打印信息 prtMem(); //打印当前已分配区表和空闲区表状态 } else if(choose == 2) { //从文件导入回收队列回收 int suc; //标识是否成功完成 char *fileName; //文件名 char *sFileName; //保存表状态的文件名 fileName = (char *)malloc(10); //为fileName分配内存 sFileName = (char *)malloc(10); //为sFileName分配内存 printf("输入回收队列文件名:"); //提示输入文件名 scanf("%s", fileName); //输入文件名 printf("输入保存表状态的文件名:"); //提示输入文件名 scanf("%s", sFileName); //输入文件名 suc = importToRecycle(fileName, sFileName); //回收 if(suc == 1) //成功 printf("回收完毕\n"); //打印信息 } else printf("choose error\n"); menu1(); scanf("%d",&choose); } } // else // printf("您输入了错误字符"); menu(); //打印菜单 scanf("%d", &c);//接受选择 } } //end of main//////////////////////////////////////