v 通过深入理解内存分配管理的三种算法,定义相应的数据结构,编写具体代码。 充分模拟三种算法的实现过程,并通过对比,分析三种算法的优劣。
v 1 )掌握内存分配 FF BF WF 策略及实现的思路;
v 2 )掌握内存回收过程及实现思路;
v 3 )参考给出的代码思路,实现内存的申请、释放的管理程序,调试运行,总结程序设计中出现的问题并找出原因,写出实验报告。

首次适应(first-fit):将空闲内存链表按开始地址从小到大排序,从链表头开始查找(也可以从上次查找结束位置),分配首个足够大的孔。

最优适应(best-fit):将空闲内存链表按大小从小到大排序,从链表头开始查找,分配首个足够大的孔。

最差适应(worst-fit):将空闲内存链表按大小从大到小排序,从链表头开始查找,分配首个足够大的孔。

内存申请原则:

     1. 找到可满足空闲分区且分配后剩余空间足够大(大于最小碎片),则分割

     2. 找到可满足空闲分区且但分配后剩余空间比较小(小于最小碎片),则一起分配

     3. 找不可满足需要的空闲分区但空闲分区之和能满足需要,则采用内存紧缩技术,进行空闲分区的合并,然后再分配

     4. 在成功分配内存后,应保持空闲分区按照相应算法有序

  内存释放原则:

             1. 将新释放的结点插入到空闲分区队列末尾

             2. 对空闲链表按照地址有序排列

             3. 检查并合并相邻的空闲分区

             4. 将空闲链表重新按照当前算法排序

代码实现:

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>#define PROCESS_NAME_LEN 32         /*进程名长度*/
#define MIN_SLICE    10             /*最小碎片的大小*/
#define DEFAULT_MEM_SIZE 1024       /*内存大小*/
#define DEFAULT_MEM_START 0         /*起始位置*/
/* 内存分配算法 */
#define MA_FF 1
#define MA_BF 2
#define MA_WF 3
int mem_size=DEFAULT_MEM_SIZE;         /*内存大小*/
int ma_algorithm = MA_FF;           /*当前分配算法*/
static int pid = 0;                 /*初始pid*/
int flag = 0;                       /*设置内存大小标志*/
/*描述每一个空闲块的数据结构*/
struct free_block_type{int size;int start_addr;struct free_block_type *next;
};  /*指向内存中空闲块链表的首指针*/
struct free_block_type *free_block;/*每个进程分配到的内存块的描述*/
struct allocated_block{int pid;    int size;int start_addr;char process_name[PROCESS_NAME_LEN];struct allocated_block *next;
};
/*进程分配内存块链表的首指针*/
struct allocated_block *allocated_block_head = NULL;/*初始化空闲块,默认为一块,可以指定大小及起始地址*/
struct free_block_type* init_free_block(int mem_size){struct free_block_type *fb;fb=(struct free_block_type *)malloc(sizeof(struct free_block_type));if(fb==NULL){printf("No mem\n");return NULL;}fb->size = mem_size;fb->start_addr = DEFAULT_MEM_START;fb->next = NULL;return fb;
}/*显示菜单*/
void display_menu(){printf("\n");printf("1 - Set memory size (default=%d)\n", DEFAULT_MEM_SIZE);printf("2 - Select memory allocation algorithm\n");printf("3 - New process \n");printf("4 - Terminate a process \n");printf("5 - Display memory usage \n");printf("0 - Exit\n");
}/*设置内存的大小*/
int set_mem_size(){int size;if(flag!=0){  //防止重复设置printf("Cannot set memory size again\n");return 0;}printf("Total memory size =");scanf("%d", &size);if(size>0) {mem_size = size;free_block->size = mem_size;}flag=1;  return 1;
}/*按FF算法重新整理内存空闲块链表*/
void rearrange_FF(){   struct free_block_type *head = free_block;int free_block_count = 0;    //计算节点数while(head != NULL) {free_block_count++;head = head->next;}int i = 0,j = 0;/*冒泡排序*/for (i;i < free_block_count - 1;i++){struct free_block_type *node = free_block;struct free_block_type *pre = free_block;j = 0;for (j;j < free_block_count - 1 - i;j++){if(node->start_addr > node->next->start_addr){ //如果前驱节点地址大于后续节点if(j == 0){free_block = node->next; //如果是前两个交换,注意更换free_block的指向struct free_block_type *temp = node->next;node->next = temp->next;temp->next = node;}else{struct free_block_type *temp = node->next;pre->next = temp;node->next = temp->next;temp->next = node;}}else{pre = node;node = node->next;}}}
}
/*按BF算法重新整理内存空闲块链表*/
void rearrange_BF(){struct free_block_type *head = free_block;int free_block_count = 0;   //计算节点数while(head != NULL) {free_block_count++;head = head->next;}int i = 0,j = 0;/*冒泡排序*/for (i;i < free_block_count - 1;i++){struct free_block_type *node = free_block;struct free_block_type *pre = free_block;j = 0;for (j;j < free_block_count - 1 - i;j++){if(node->size > node->next->size){ //如果前驱节点size大于后续节点if(j == 0){free_block = node->next;   //如果是前两个交换,注意更换free_block的指向struct free_block_type *temp = node->next;node->next = temp->next;temp->next = node;}else{struct free_block_type *temp = node->next;pre->next = temp;node->next = temp->next;temp->next = node;}}else{pre = node;node = node->next;}}}
}
/*按WF算法重新整理内存空闲块链表*/
void rearrange_WF(){struct free_block_type *head = free_block;int free_block_count = 0;   //计算节点数while(head != NULL) {free_block_count++;head = head->next;}int i = 0,j = 0;/*冒泡排序*/for (i;i < free_block_count - 1;i++){struct free_block_type *node = free_block;struct free_block_type *pre = free_block;j = 0;for (j;j < free_block_count - 1 - i;j++){if(node->size < node->next->size){ //如果前驱节点size小于后续节点if(j == 0){free_block = node->next;  //如果是前两个交换,注意更换free_block的指向struct free_block_type *temp = node->next;node->next = temp->next;temp->next = node;}else{struct free_block_type *temp = node->next;pre->next = temp;node->next = temp->next;temp->next = node;}}else{pre = node;node = node->next;}}}
}/*按指定的算法整理内存空闲块链表*/
void rearrange(int algorithm){switch(algorithm){case MA_FF:  rearrange_FF(); break;case MA_BF:  rearrange_BF(); break;case MA_WF:  rearrange_WF(); break;}
}/* 设置当前的分配算法 */
void set_algorithm(){int algorithm;printf("\t1 - First Fit\n");printf("\t2 - Best Fit \n");printf("\t3 - Worst Fit \n");scanf("%d", &algorithm);if(algorithm>=1 && algorithm <=3)  ma_algorithm=algorithm;//按指定算法重新排列空闲区链表rearrange(ma_algorithm);
}/*创建新的进程,主要是获取内存的申请数量*/
int new_process(){struct allocated_block *ab;int size;    int ret;ab=(struct allocated_block *)malloc(sizeof(struct allocated_block));if(!ab) exit(-5);ab->next = NULL;pid++;sprintf(ab->process_name, "PROCESS-%02d", pid);ab->pid = pid;    printf("Memory for %s:", ab->process_name);scanf("%d", &size);if(size>0) ab->size=size;ret = allocate_mem(ab);  /* 从空闲区分配内存,ret==1表示分配ok*//*如果此时allocated_block_head尚未赋值,则赋值*/if((ret==1) &&(allocated_block_head == NULL)){ allocated_block_head=ab;ab->next = NULL;return 1;        }/*分配成功,将该已分配块的描述插入已分配链表*/else if (ret==1) {ab->next=allocated_block_head;allocated_block_head=ab;return 2; }else if(ret==-1){ /*分配不成功*/printf("Allocation fail\n");free(ab);return -1;       }return 3;
}
/*内存紧缩操作*/
void mem_compact(int sliceSize){    //参数为所有空闲内存大小struct allocated_block *ab = allocated_block_head;free_block->start_addr = 0;free_block->size = sliceSize;free_block->next = NULL;        //紧缩原则是空闲内存从地址0开始while(ab != NULL){ab->start_addr = sliceSize;sliceSize += ab->size;ab = ab->next;}
}
/*分配内存模块*/
int allocate_mem(struct allocated_block *ab){struct free_block_type *fbt, *pre;int request_size=ab->size;fbt = pre = free_block;int totalSize = 0;if(fbt == NULL) return -1;   //如果空闲内存为空,则分配失败while (fbt != NULL){totalSize += fbt->size;        //计算所有孔大小if (fbt->size >= request_size){     //如果找到大小足够的孔,分两种情况if(fbt->size - request_size >= MIN_SLICE){      //1.孔足够大,无内部碎片,重新分割。空闲孔顺序不变。ab->start_addr = fbt->start_addr;fbt->start_addr = fbt->start_addr + request_size;fbt->size = fbt->size - request_size;}else{                                   //2.孔不够大,产生内部碎片,直接分配。空闲孔顺序改变。ab->size = fbt->size;ab->start_addr = fbt->start_addr;if (fbt == free_block) free_block = fbt->next;else pre->next = fbt->next;               //删除目前空闲孔}return 1;}else{                       //目前孔不够大,则查找后续空闲孔pre = fbt;fbt = fbt->next;}}//单个孔无法满足需求,考虑内存紧缩if (totalSize >= request_size){           //所有孔大小和大于需求,可以进行紧缩mem_compact(totalSize);               //紧缩操作if(totalSize - request_size >= MIN_SLICE){        //1.孔足够大,无内部碎片,重新分割。空闲孔顺序不变。free_block->size = free_block->size - request_size;ab->start_addr = free_block->size;}else{                             //2.孔不够大,产生内部碎片,直接分配。空闲孔顺序改变。free_block->size = 0;free_block = NULL;ab->start_addr = free_block->start_addr;}return 1;}else return -1;    //无法紧缩,分配失败。}/*找到id为pid的进程并返回*/
struct allocated_block* find_process(int pid){struct allocated_block *ab;ab = allocated_block_head;while(ab != NULL){if (ab->pid == pid) return ab;ab = ab->next;}printf("can't find process %d",pid);return NULL;
}/*删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点*/
void kill_process(){struct allocated_block *ab;int pid;printf("Kill Process, pid=");scanf("%d", &pid);ab=find_process(pid);if(ab!=NULL){free_mem(ab); /*释放ab所表示的分配区*/dispose(ab);  /*释放ab数据结构节点*/}
}/*将ab所表示的已分配区归还,并进行可能的合并*/
int free_mem(struct allocated_block *ab){int algorithm = ma_algorithm;struct free_block_type *fbt, *pre, *work;fbt=(struct free_block_type*) malloc(sizeof(struct free_block_type));pre=(struct free_block_type*) malloc(sizeof(struct free_block_type));if(!fbt) return -1;fbt->size = ab->size;fbt->start_addr = ab->start_addr;//1.插到队尾work = free_block;      if(work == NULL){free_block = work;work->next = NULL;}else{while(work->next != NULL) work = work->next;work->next = fbt;fbt->next = NULL;}//2.按地址有序排列rearrange_FF();//3.合并相邻空闲分区pre = free_block;if(pre != NULL){work = pre->next;while(work != NULL){work = pre->next;if(pre->start_addr + pre->size == work->start_addr) {pre->next = work->next;pre->size += work->size;free(work);}else pre = pre->next;if(pre != NULL) work = pre->next;else work = NULL;}}//按当前算法重新排序rearrange(algorithm);// 进行可能的合并,基本策略如下// 1. 将新释放的结点插入到空闲分区队列末尾// 2. 对空闲链表按照地址有序排列// 3. 检查并合并相邻的空闲分区// 4. 将空闲链表重新按照当前算法排序return 1;
}/*释放ab数据结构节点*/
int dispose(struct allocated_block *free_ab){struct allocated_block *pre, *ab;if(free_ab == allocated_block_head) { /*如果要释放第一个节点*/allocated_block_head = allocated_block_head->next;free(free_ab);return 1;}pre = allocated_block_head;  ab = allocated_block_head->next;while(ab!=free_ab){ pre = ab;  ab = ab->next; }pre->next = ab->next;free(ab);return 2;
}
/* 显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 */
int display_mem_usage(){struct free_block_type *fbt=free_block;struct allocated_block *ab=allocated_block_head;if(fbt==NULL) return(-1);printf("----------------------------------------------------------\n");/* 显示空闲区 */printf("Free Memory:\n");printf("%20s %20s\n", "      start_addr", "       size");while(fbt!=NULL){printf("%20d %20d\n", fbt->start_addr, fbt->size);fbt=fbt->next;}/* 显示已分配区 */printf("\nUsed Memory:\n");printf("%10s %20s %10s %10s\n", "PID", "ProcessName", "start_addr", " size");while(ab!=NULL){printf("%10d %20s %10d %10d\n", ab->pid, ab->process_name, ab->start_addr, ab->size);ab=ab->next;}printf("----------------------------------------------------------\n");return 0;
}int main(){char choice;      pid=0;free_block = init_free_block(mem_size); //初始化空闲区while(1) {display_menu();     //显示菜单fflush(stdin);choice=getchar();  //获取用户输入switch(choice){case '1': set_mem_size(); break;   //设置内存大小case '2': set_algorithm();flag=1; break;//设置算法case '3': new_process(); flag=1; break;//创建新进程case '4': kill_process(); flag=1;   break;//删除进程case '5': display_mem_usage();    flag=1; break;    //显示内存使用case '0': exit(0);    //释放链表并退出default: break;      }while(1){if(getchar() == '\n') break;}} return 0;
}

参考资料:《操作系统概念(第九版)》

二、内存管理与多进程(含源码)_稳健的不高冷的强哥的博客-CSDN博客

内存分配---FF、BF、WF三种算法_weixin_30878501的博客-CSDN博客

Linux内存分配--实现FF、BF、WF分配算法相关推荐

  1. linux内存管理实验malloc,linux内存管理实验报告.doc

    linux内存管理实验报告 操作系统实验报告 院别:XXXXXX 班级:XXXXXX 学号:XXXXXX 姓名:稻草人 实验题目:内存管理实验 实验目的 通过本次试验体会操作系统中内存的分配模式: 掌 ...

  2. Linux系统内存管理实验报告,linux内存管理实验报告

    <linux内存管理实验报告>由会员分享,可在线阅读,更多相关<linux内存管理实验报告(13页珍藏版)>请在人人文库网上搜索. 1.操作系统实验报告院别:XXXXXX班级: ...

  3. 深入理解Linux内存管理--目录导航

    日期 内核版本 架构 作者 GitHub CSDN 2016-08-31 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 1 ...

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

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

  5. linux内存分配 连续 足够,linux内存池能分配连续物理内存吗

    中. size参数: 内核是基于页技术分配内存,以最佳的利用系统的RAM. linux处理内存分配的方法是:创建一系列的内存对象池,每个池的内存大小事固定的,处理分配请求时,就直接在包含足够大的内存块 ...

  6. linux为系统分配内存,Linux操作系统知识讲解:走进Linux 内存分配算法

    Linux 内存分配算法 内存管理算法--对讨厌自己管理内存的人来说是天赐的礼物 1.内存碎片 1) 基本原理 产生原因:内存分配较小,并且分配的这些小的内存生存周期又较长,反复申请后将产生内存碎片的 ...

  7. linux c语言 glibc 错误 munmap,Linux内存分配小结--malloc、brk、mmap

    Linux的虚拟内存管理有几个关键概念: 1.每个进程都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址: 2.虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟空间地址)与物理地址进行 ...

  8. Linux内存管理 (4)分配物理页面

    专题:Linux内存管理专题 关键词:分配掩码.伙伴系统.水位(watermark).空闲伙伴块合并. 我们知道Linux内存管理是以页为单位进行的,对内存的管理是通过伙伴系统进行. 从Linux内存 ...

  9. C/C++内存分配与Linux内存管理进程所涉及到的五个数据段 .

    一. 在c中分为这几个存储区 1.栈 - 由编译器自动分配释放 2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 3.全局区(静态区),全局变量和静态变量的存储是放在一块的, ...

最新文章

  1. 基于视觉的数学公式识别算法介绍
  2. l3fwd 是什么_服务器DPDK l3fwd性能测试
  3. linux使用环境实验报告,Linux 及其使用环境实验报告.doc
  4. Navicat Premium试用期破解方法(转)
  5. 学会放松,是通向生命觉‮的醒‬必经之路
  6. ssh连接aix问题与解决
  7. Mysql和vs2010 的连接
  8. java swt 双屏_SWT(JFace)体验之打开多个Form
  9. javascript手机号码、电子邮件正则表达式 一种解决方案
  10. MapReduce Shuffle详解
  11. 期末前端web大作业——用前端语言写一个小游戏
  12. 树莓派3 linux,树莓派
  13. 计算机键盘快速指南,正确方法:[字母键盘练习方法指南]教您如何快速键入
  14. TIA西门子博途V17安装教程及注意事项
  15. java时钟课程设计,Java课程设计-时钟图形模拟
  16. JDK的下载与安装配置教程2022最新
  17. 2018,程序员生活的两个兴趣爱好
  18. 目前游戏行业内部主要几款游戏引擎的技术对比(转)
  19. 简明量子力学的学习 量子计算 笔记量子概念
  20. 物联网平台是什么,怎么选择合适的物联网平台?

热门文章

  1. 2022年热门职业排行
  2. 微信小程序开发|基于微信小程序的健身陪练系统的设计与实现
  3. 基于蛾群算法的函数寻优算法
  4. win10 热点开启后 ip4无网络访问权限
  5. 通过微信OCR识别获取身份证信息
  6. html怎么与ps结合,PS和ai怎么配合使用好 用ai和PS结合做方法流程?
  7. python 类实例化后作为参数_python--类的实例化
  8. 计算机专业英语推荐信,英文推荐信
  9. 信息爆炸式增长让海量数据创造最大价值
  10. 大揭秘(2):网店背后的隐秘产业链【连载】