湖南师范大学 信息科学与工程学院 操作系统课程实验报告

实验项目名称: 可变分区存储管理

题目

实验一、可变分区存储管理
一、实验目的:

  1. 加深对可变分区存储管理的理解;
  2. 提高用C语言编制大型系统程序的能力,特别是掌握C语言编程的难点:指针和指针作为函数参数;
  3. 掌握用指针实现链表和在链表上的基本操作。
    二、实验内容:
    参照教材P137-P140的内容,编写一个C程序,用char *malloc(unsigned size)函数向系统申请一次内存空间(如size=1000,单位为字节),用循环首次适应算法、最佳适应算法和最坏适应算法,模拟可变分区存储管理,实现对内存区的分配和回收管理。
    三、实验要求:
  4. 分配函数addr=(char *)lmalloc(unsigned size)和释放函数lfree(unsigned size,char *addr)的参数size和addr,要以键盘命令的形式输入,每次分配和释放后显示空闲分区表。
  5. 空闲分区表可采用结构数组的形式(最低要求)或双向链表的形式。
    四、参考测试数据:
    操作系统在低地址占用100KB的空间,用户区主存从100KB处开始占用512KB。初始时,用户区全部为空闲,分配时截取空闲分区的低地址部分作为已分配区。执行以下申请、释放操作序列后:请求300KB,请求100KB,释放300KB,请求150KB,请求90KB,释放100KB。

代码实现

#include "stdio.h"
#include "iostream"
using namespace std;void firstmethod();
void bestmethod();
void badmethod();int main()
{int menu;do{cout << "------------------------------------------" << endl;cout << "\n菜单:\n1.循环首次适应算法\n2.最佳适应算法\n3.最坏适应算法\n-------\n输入0结束程序\n请输入你要执行的操作:\n";cout << "------------------------------------------" << endl;cin >> menu;switch (menu){case 1:cout << "*******************循环首次适应算法**********************" << endl;firstmethod();cout << "********************************************************" << endl;break;case 2:cout << "*********************最佳适应算法************************" << endl;bestmethod();cout << "********************************************************" << endl;break;case 3:cout << "*********************最坏适应算法************************" << endl;badmethod();cout << "********************************************************" << endl;break;case 0:break;default:cout << "输入错误,请重新选择操作" << endl;break;}} while (menu != 0);
}typedef struct Double_linked_list
{//char name[10];//进程名int flag;                                //1为已分配,0为空闲unsigned int size;                       //所指分区的大小char *addr;                              //分区起始地址struct Double_linked_list *prior, *next; //本表项的前后表项
} DllNode, *Dll;Dll first, current; //首表项与起始查询指针unsigned start; //主存起始地址
char *p;        //地址的开始//初始化空闲分区表
void initDll()
{first = (Dll)malloc(sizeof(DllNode));if (!first){//分配失败exit(0);}printf("请输入你要设置的主存起始地址:\n");cin >> start;printf("请输入你要设置的主存大小:\n");cin >> first->size;p = (char *)malloc(first->size + start);first->addr = p + start;first->flag = 0;first->next = first->prior = NULL;
}void printDll()
{Dll tmp = first;cout << "\n\n-----------------free table---------------" << endl;while (tmp != NULL){if (!tmp->flag)printf("起始地址:%4u,大小:%4d,结束地址:%4u\n", tmp->addr - p, tmp->size, tmp->addr - p + tmp->size - 1);tmp = tmp->next;}cout << "------------------------------------------" << endl;tmp = first;cout << "----------------allowcation table---------" << endl;while (tmp != NULL){if (tmp->flag)printf("起始地址:%4u,大小:%4d,结束地址:%4u\n", tmp->addr - p, tmp->size, tmp->addr - p + tmp->size - 1);tmp = tmp->next;}cout << "------------------------------------------\n\n"<< endl;
}int lmalloc(unsigned size)
{if (size <= 0){cout << "分配大小错误" << endl;return 1;}Dll tmp = current;Dll newNode = (Dll)malloc(sizeof(DllNode));if (!newNode)exit(0);newNode->flag = 1;newNode->size = size;do{if (current->flag == 1){ //已分配的区域跳过current = current->next;if (!current){current = first;}continue;}if (current->size > size){ //大于所需空间if (current == first){first = newNode;if (current->next == current){current->next = first;}current->prior = newNode;}else{current->prior->next = newNode;}newNode->prior = current->prior;newNode->next = current;current->prior = newNode;newNode->addr = current->addr;current->addr += size;current->size -= size;return 1;}else if (current->size == size){ //等于所需空间current->flag = 1;current = current->next;if (current == NULL){current = first;}return 1;}else{ //小于所需空间current = current->next;}if (current == NULL){current = first;}} while (tmp != current);return 0;
}int lfree(unsigned size, unsigned addr)
{Dll tmp = first;do{//为空闲分区则跳过if (tmp->flag == 0){tmp = tmp->next;continue;}//起始地址或大小不符if (tmp->addr - p != addr || tmp->size != size){tmp = tmp->next;continue;}//回收链表第一个节点if (tmp->prior == NULL){//链表只有一个节点if (tmp->next == NULL){tmp->flag = 0;return 1;}//链表的第一个节点且后面有节点else{//回收链表的第一个节点且后面一个节点为空闲分区if (!tmp->next->flag){tmp->size += tmp->next->size;Dll p = tmp->next;tmp->next = tmp->next->next;tmp->flag = 0;free(p);return 1;}//回收链表的第一个节点且后面一个节点不是空闲分区else{tmp->flag = 0;return 1;}}}if (tmp->next == NULL){ //回收链表最后一个节点if (!tmp->prior->flag){ //前面的节点是空闲分区tmp->prior->size += tmp->size;tmp->prior->next = tmp->next;free(tmp);return 1;}else{ //前面分区已分配tmp->flag = 0;return 1;}}//此时的节点不是首尾分区//回收分区前有空闲分区if (!tmp->prior->flag){//回收分区前后都有空闲分区if (!tmp->next->flag){tmp->prior->size += tmp->size + tmp->next->size;tmp->prior->next = tmp->next->next;free(tmp->next);free(tmp);return 1;}//回收分区后没有空闲分区else{tmp->prior->size += tmp->size;tmp->prior->next = tmp->next;free(tmp);return 1;}}//回收分区前没有空闲分区else{//回收分区后有空闲分区if (!tmp->next->flag){tmp->size += tmp->next->size;Dll p = tmp->next;tmp->next = tmp->next->next;tmp->flag = 0;free(p);return 1;}//回收分区前后都没有else{tmp->flag = 0;return 1;}}} while (tmp != NULL);//没有要释放的分区return 0;
}void firstmethod()
{int menu;initDll();current = first;unsigned size, addr;do{printDll();cout << "------------------------------------------\n菜单:\n1.申请内存\n2.释放内存\n------------------------------------------\n输入0结束本次算法\n";cin >> menu;switch (menu){case 1:cout << "请输入申请内存大小:" << endl;cin >> size;if (!(lmalloc(size))){cout << "内存不足,分配失败" << endl;}break;case 2:cout << "请输入要释放的起始地址" << endl;cin >> addr;cout << "请输入要释放的地址大小:" << endl;cin >> size;if (!lfree(size, addr)){cout << "命令错误,请检查分配表" << endl;}break;case 0:free(first);break;default:cout << "输入错误,请重新选择操作" << endl;break;}} while (menu != 0);
}void swap_Dll(Dll &L1, Dll &L2)
{char *p = L1->addr;L1->addr = L2->addr;L2->addr = p;int flag = L1->flag;L1->flag = L2->flag;L2->flag = flag;int size = L1->size;L1->size = L2->size;L2->size = size;
}void sortDll_ASC_size(Dll &L)
{Dll p, q;for (p = L; p->next != NULL; p = p->next){for (q = p->next; q != NULL; q = q->next){if (p->size > q->size){swap_Dll(p, q);}}}
}
void sortDll_DSC_size(Dll &L)
{Dll p, q;for (p = L; p->next != NULL; p = p->next){for (q = p->next; q != NULL; q = q->next){if (p->size < q->size){swap_Dll(p, q);}}}
}
void sortDll_ASC_addr(Dll &L)
{Dll p, q;for (p = L; p->next != NULL; p = p->next){for (q = p->next; q != NULL; q = q->next){if (p->addr > q->addr){swap_Dll(p, q);}}}
}int lmalloc_other(unsigned size)
{if (size <= 0){cout << "分配大小错误" << endl;return 1;}Dll tmp = first;Dll newNode = (Dll)malloc(sizeof(DllNode));if (!newNode)exit(0);newNode->flag = 1;newNode->size = size;do{if (tmp->flag == 1){ //已分配的区域跳过tmp = tmp->next;continue;}if (tmp->size > size){ //大于所需空间//第一个节点if (tmp == first){first = newNode;newNode->prior = NULL;}else{tmp->prior->next = newNode;newNode->prior = tmp->prior;}newNode->next = tmp;tmp->prior = newNode;newNode->addr = tmp->addr;tmp->addr += size;tmp->size -= size;return 1;}else if (tmp->size == size){ //等于所需空间tmp->flag = 1;tmp = tmp->next;return 1;}else{ //小于所需空间tmp = tmp->next;}} while (tmp != NULL);return 0;
}void bestmethod()
{int menu;initDll();unsigned size, addr;do{printDll();cout << "------------------------------------------\n菜单:\n1.申请内存\n2.释放内存\n------------------------------------------\n输入0结束本次算法\n";cin >> menu;switch (menu){case 1:sortDll_ASC_size(first);cout << "请输入申请内存大小:" << endl;cin >> size;if (!(lmalloc_other(size))){cout << "内存不足,分配失败" << endl;}sortDll_ASC_addr(first);break;case 2:sortDll_ASC_addr(first);cout << "请输入要释放的起始地址" << endl;cin >> addr;cout << "请输入要释放的地址大小:" << endl;cin >> size;if (!lfree(size, addr)){cout << "命令错误,请检查分配表" << endl;}break;case 0:free(first);break;default:cout << "输入错误,请重新选择操作" << endl;break;}} while (menu != 0);
}void badmethod()
{int menu;initDll();unsigned size, addr;do{printDll();cout << "------------------------------------------\n菜单:\n1.申请内存\n2.释放内存\n------------------------------------------\n输入0结束本次算法\n";cin >> menu;switch (menu){case 1:sortDll_DSC_size(first);cout << "请输入申请内存大小:" << endl;cin >> size;if (!(lmalloc_other(size))){cout << "内存不足,分配失败" << endl;}sortDll_ASC_addr(first);break;case 2:sortDll_ASC_addr(first);cout << "请输入要释放的起始地址" << endl;cin >> addr;cout << "请输入要释放的地址大小:" << endl;cin >> size;if (!lfree(size, addr)){cout << "命令错误,请检查分配表" << endl;}break;case 0:free(first);break;default:cout << "输入错误,请重新选择操作" << endl;break;}} while (menu != 0);
}

实验结果分析

操作系统在低地址占用100KB的空间,用户区主存从100KB处开始占用512KB。初始时,用户区全部为空闲,分配时截取空闲分区的低地址部分作为已分配区。执行以下申请、释放操作序列后:请求300KB,请求100KB,释放300KB,请求150KB,请求90KB,释放100KB。
首次循环适应算法
最佳适应算法
最坏适应算法

心得体会

这次实验是实现动态分区分配中循环首次适应算法,最佳适应算法和最坏适应算法,三种算法大同小异,在循环首次适应算法中,需要注意的是用current指针指向上一次分配后的空闲分区,在分配时从current指向的分区开始查询。而最佳适应算法和最坏适应算法只需将空闲分区在分配前分别按升序和降序进行排列,在分配后对地址进行升序排列,剩下的分配和回收细节基本相同。

用循环首次适应算法、最佳适应算法和最坏适应算法,模拟可变分区存储管理,实现对内存区的分配和回收管理相关推荐

  1. c模拟内存分配算法(首次适应算法,最佳适应算法,最坏适应算法)

    #include<bits/stdc++.h> using namespace std; /*定义内存的大小为100*/ #define MEMSIZE 100 /*如果小于此值,将不再分 ...

  2. 【操作系统】-- 动态分区分配算法(首次适应算法FF、最佳适应算法BF、最坏适应算法WF、循环首次适应算法NF)

    一.首次适应算法 1.算法思想 每次从低地址开始查找,找到第一个能满足大小的空闲分区. 2.如何实现 空闲分区以地址递增的次序排列,每次分配内存时顺序查找空闲分区链,找到大小能满足要求的第一个空闲分区 ...

  3. 操作系统——动态分配算法(首次适应算法,最佳适应算法,最坏适应算法及回收)

    操作系统--动态分配 写的时间早了,有些许漏洞和不足,请大家不要介意 分配方式可分为四类:单一连续分配.固定分区分配.动态分区分配以及动态可重定位分区分配算法四种方式,其中动态分区分配算法就是此实验的 ...

  4. 循环首次适应算法_数据结构与算法之2——排序问题

    排序真的是数据结构与算法中的重中之重啊,无论是对编程能力的提升,以后工作后的应用,或者是应对面试的时候都是经常需要用到的.基本的几个经典排序一定要做到滚瓜烂熟,能够做到给你一个具体的排序算法题,一定能 ...

  5. 最坏适应算法c语言源码,首次适应算法,最佳适应算法,最坏适应算法源代码

    这是一个非常完美的程序,输出显示的格式也很棒,里面包含首次适应算法,最佳适应算法,最坏适应算法 #include #include #define Free 0 //空闲状态 #define Busy ...

  6. 操作系统【动态分区分配算法——首次适应算法、最佳适应算法、最坏适应算法、临近适应算法】

    学习地址(哔哩哔哩网站--王道论坛):https://www.bilibili.com/video/BV1YE411D7nH?p=37 目录 1.首次适应算法(First Fit) 2.最佳适应算法( ...

  7. 连续分配管理方式的动态分区分配算法(首次适应、最佳适应、最坏适应、邻接适应算法)

    一.动态分区分配算法(连续分配管理方式) 动态分区分配算法:在动态分区分配方式中, 当很多个空闲分区都能满足需求时,应该选择哪个分区进行分配? (一)首次适应算法 算法思想:每次都从低地址开始查找,找 ...

  8. 3.1.5 操作系统之动态分区分配的四种算法(首次适应算法、最佳适应算法、最坏适应算法、临近适应算法)

    文章目录 0.思维导图 1.首次适应算法 2.最佳适应算法 3.最坏(大)适应算法 4.临近适应算法 5.四种算法归纳比较 0.思维导图 本篇文章是对上一篇文章内存的分配与回收提到的动态分区分配算法的 ...

  9. 利用for循环调用插入方法批量插入 一条失败_算法与数据结构(1):基础部分——以插入排序为例...

    本文将会以插入排序为例,介绍算法与数据结构的基础部分. 插入排序 排序可以说是整个算法中最为基础,最为重要的一部分,而插入排序正是排序算法中最简单的一种解决办法. 什么是排序问题? 输入:n个数的一个 ...

最新文章

  1. Qt/Linux 下的摄像头捕获(Video4Linux2)
  2. java action的头文件注释_有没有java大神,帮我详细注释下面的代码,action里面复制来的...
  3. Fabio技术手册(1):概述和快速上手
  4. 删除右键菜单中的选项:在Visual Studio中打开
  5. 终极指南:如何使用Visual Studio Code进行 Java 开发?
  6. Hibernate 一对一外键单向关联
  7. 数据结构 5-2 二叉树建树
  8. python有比赛吗_python编程比赛到底应不应该让孩子参加?有好处
  9. java接口测试工具_接口模拟测试利器,moco server工具的介绍
  10. ruby语言+Devkit 工具
  11. 原生Android应用接入flutter(详细步骤)
  12. oppok1掉色吗?_如何对旧的褪色照片进行色彩校正
  13. ETL KETTLE 读取csv文件写入数据库
  14. 小程序组件-仿微信通讯录
  15. Python matplotlib数据可视化 subplot绘制多个子图
  16. 爬取立创商城lcsc的元件厂商列表以及元件汇总(附源码)
  17. 学术期刊划分(教你认识SCI、EI、SSCI、IEEE、CSSCI...)
  18. 第八篇:读《反脆弱》
  19. Win10页面缓冲池剧增占用内存解决方案
  20. 终于可以携号转网,三大运营商做了10年,技术难点到底在哪?

热门文章

  1. 20155220 吴思其 《网络攻防》 Exp1 PC平台逆向破解(5)M
  2. 机器学习:k-means聚类算法+算法优化
  3. 《刨根问底系列》01:操作系统凭什么可以调度程序?
  4. 计算机毕业设计springcloud房产销售平台
  5. 位运算符+位运算的应用
  6. Linux下Open函数
  7. c语言处理用户错误输入,C语言实现用户输入
  8. Spring boot 发送手机验证码
  9. GO富集分析可视化——柱形图和棒棒糖图
  10. 27款国外最新Photoshop色板