操作系统#内存管理设计性实验报告

正文

一、 实验目的
1.通过本次试验体会操作系统中内存的分配模式;
2.掌握内存分配的方法(首次适应(FF),最佳适应(BF),最差适应(WF));
3.学会进程的建立,当一个进程被终止时内存是如何处理被释放块,并当内存不满足进程申请时是如何使用内存紧凑;
4.掌握内存回收过程及实现方法;
5.学会进行内存的申请释放和管理;

二、 实验设备

实验机房虚拟机里的中linux系统

三、 实验要求

1、运行如下的内存申请与释放序列:先设置内存大小为2048k,进程1申请500k,进程2申请300k,进程1完成,进程3申请200k,进程4申请100k,进程5申请300k;

2、分别选择不同的内存分配算法,输出上述序列的内存分配结果;

3、实现循环首次适应算法,并输出上述序列采用该分配算法后的结果。

四、 实验步骤

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.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      3int mem_size = DEFAULT_MEM_SIZE;         /*内存大小*/
int ma_algorithm = MA_FF;              /*当前分配算法*/
int flag = 0;                         /*设置内存大小标志*/
static int pid = 0;                    /*初始pid*/
int algorithm;/*描述每一个空闲块的数据结构*/
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 allocated_block* find_process(int id)
{struct allocated_block* p;p = allocated_block_head;while (p != NULL){if (p->pid == id)p = p->next;return p;}return NULL;
}void swap(int* p, int* q)
{int temp;temp = *p;*p = *q;*q = temp;return;
}void do_exit()
{exit(0);
}/*初始化空闲块,默认为一块,可以指定大小及起始地址*/
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;
}/*显示菜单*/
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");
}/*设置内存的大小*/
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算法重新整理内存空闲块链表*/
rearrange_FF() {struct free_block_type* tmp, * work;printf("Rearrange free blocks for FF \n");tmp = free_block;while (tmp != NULL){work = tmp->next;while (work != NULL) {if (work->start_addr > tmp->start_addr){ /*地址递增*/swap(&work->start_addr, &tmp->start_addr);swap(&work->size, &tmp->size);}work = work->next;}tmp = tmp->next;}
}/*按BF最佳适应算法重新整理内存空闲块链表*/rearrange_BF() {struct free_block_type* tmp, * work;printf("Rearrange free blocks for BF \n");tmp = free_block;while (tmp != NULL){work = tmp->next;while (work != NULL) {if (work->size < tmp->size) { /*地址递增*/swap(&work->start_addr, &tmp->start_addr);swap(&work->size, &tmp->size);}work = work->next;}tmp = tmp->next;}
}/*按WF算法重新整理内存空闲块链表*/rearrange_WF() {struct free_block_type* tmp, * work;printf("Rearrange free blocks for WF \n");tmp = free_block;while (tmp != NULL){work = tmp->next;while (work != NULL) {if (work->size < tmp->size) { /*地址递增*/swap(&work->start_addr, &tmp->start_addr);swap(&work->size, &tmp->size);}elsework = work->next;}tmp = tmp->next;}
}/*按指定的算法整理内存空闲块链表*/
rearrange(int algorithm) {switch (algorithm) {case MA_FF:  rearrange_FF(); break;case MA_BF:  rearrange_BF(); break;case MA_WF:  rearrange_WF(); break;}
}/* 设置当前的分配算法 */
set_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 allocate_mem(struct allocated_block* ab) {struct free_block_type* fbt, * pre, * temp, * work;int request_size = ab->size;fbt = free_block;while (fbt != NULL){if (fbt->size >= request_size){if (fbt->size - request_size >= MIN_SLICE) /*分配后空闲空间足够大,则分割*/{mem_size -= request_size;fbt->size -= request_size;ab->start_addr = fbt->start_addr;fbt->start_addr += request_size;}else  if (((fbt->size - request_size) < MIN_SLICE) && ((fbt->size - request_size) > 0))/*分割后空闲区成为小碎片,一起分配*/{mem_size -= fbt->size;pre = fbt->next;ab->start_addr = fbt->start_addr;fbt->start_addr += fbt->size;free(fbt);}else{temp = free_block;while (temp != NULL){work = temp->next;if (work != NULL)/*如果当前空闲区与后面的空闲区相连,则合并*/{if (temp->start_addr + temp->size == work->start_addr){temp->size += work->size;temp->next = work->next;free(work);continue;}}temp = temp->next;}fbt = free_block;break;}rearrange(algorithm); /*重新按当前的算法排列空闲区*/return 1;}pre = fbt;fbt = fbt->next;}return -1;
}/*创建新的进程,主要是获取内存的申请数量*/
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;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;
}/*将ab所表示的已分配区归还,并进行可能的合并*/
int free_mem(struct allocated_block* ab)
{int algorithm = ma_algorithm;struct free_block_type* fbt, * work;fbt = (struct free_block_type*)malloc(sizeof(struct free_block_type));if (!fbt) return -1;fbt->size = ab->size;fbt->start_addr = ab->start_addr;/*插入到空闲区链表的头部并将空闲区按地址递增的次序排列*/fbt->next = free_block;free_block = fbt;rearrange(MA_FF);fbt = free_block;while (fbt != NULL) {work = fbt->next;if (work != NULL){/*如果当前空闲区与后面的空闲区相连,则合并*/if (fbt->start_addr + fbt->size == work->start_addr){fbt->size += work->size;fbt->next = work->next;free(work);continue;}}fbt = fbt->next;}rearrange(algorithm); /*重新按当前的算法排列空闲区*/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;
}/* 显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 */
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;
}/*删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点*/
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数据结构节点*/}
}main()
{char choice;pid = 0;free_block = init_free_block(mem_size); //初始化空闲区for (;;){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':   do_exit(); exit(0);                break;       //释放链表并退出default: break;}}
}

五、结果分析与总结





FF算法是以空闲链的首地址递增顺序组织起来,当提出分配需求时,遍历组织好的空白链,找到第一个空间大于等于分配需求的空白分配块分配。若遍历一遍都未找到满足需求的空白块,则分配失败;BF“最佳”指的是大小合适,最接近。空白链以容量大小的顺序组织,每次遍历空白链查找第一个能满足需求的空白块进行分配,这样就一定程度减少了外部碎片的大小。也避免了“大材小用”;WF最坏适应算法和最佳使用算法的空白块选择策略刚好相反,它在扫描整个空表链时,总是挑选一个最大空闲块,从中分割需求的内存块,实际上,这样的算法未必是最坏的
循环首次适应算法的排序方式和首次适应算法相同(查找的起始位置不同),在修改过程中添加一个指针来指明上次查找的位置,从而从下次查找时从此处开始。在从特定位置进行查找时,查找结束的标志有所改变,前面几种结束的表示均是到链尾,而循环首次适应算法查找结束标志是再次查找特定位置。

【操作系统】内存管理设计性实验报告相关推荐

  1. 计算机组成原理设计性实验,《计算机组成原理》设计性实验报告.doc

    <计算机组成原理>设计性实验报告 华北科技学院计算机学院设计性实验 实 验 报 告 课程名称 计算机组成原理B 实验学期 2013 至 2014 学年 第 一 学期 学生所在院部 计算机学 ...

  2. 计算机操作系统进程同步实验报告,操作系统-进程管理与进程同步-实验报告

    进程管理与进程同步实验报告 实验一.进程管理与进程同步 一.实验目的 了解进程管理的实现方法,理解和掌握处理进程同步问题的方法. 二.实验内容 实现银行家算法.进程调度过程的模拟.读者-写者问题的写者 ...

  3. JAVA第二次验证设计性实验报告

    [实验任务一]:素数输出 (3)实验报告中要求包括程序设计思想.程序流程图.源代码.运行结果截图.编译错误分析等内容. 1.   实验内容 (1)计算并输出3~100之间的素数. (2)编程满足下列要 ...

  4. 操作系统 内存管理总结

    目录 内存管理介绍 什么是虚拟内存(Virtual Memory)? 逻辑(虚拟)地址和物理地址 CPU 寻址了解吗?为什么需要虚拟地址空间? 局部性原理 操作系统是如何管理虚拟地址与物理地址之间的关 ...

  5. 用C语言编程实现矩形波信号,信号与系统综合设计性实验

    信号与系统综合设计性实验 傅立叶变换性质 实验设备 硬件 电脑软件 MATLAB 实验目的 掌握MATLAB的基本使用方法 掌握MATLAB环境下信号表示及产生方法 掌握MATLAB环境下傅立叶变换方 ...

  6. 操作系统内存管理-Linux版

    引言 操作系统内存管理:总的来说,操作系统内存管理包括物理内存管理和虚拟内存管理. 物理内存管理: 包括程序装入等概念.交换技术.连续分配管理方式和非连续分配管理方式(分页.分段.段页式). 虚拟内存 ...

  7. 计算机图形人机交互实验报告,用户界面设计人机交互实验报告.doc

    用户界面设计人机交互实验报告 <人机交互>实验报告 题目 实验一 图形用户界面的设计 专业 软件工程 班级 2011 学号 2011221104220026 姓名 孙元喜 导教师 关玉欣 ...

  8. 大物设计性实验:电容、电感量的测量

    这是最后一次大物实验,仅以此文作为纪念. 下面是华南某大学的设计性实验: 一. 实验内容和要求 1.根据实验室所提供的仪器拟定测量电容量.电感量的实验电路.各构思3种以上的测量方法,写出实验步骤及运算 ...

  9. 数字电路实验六:同步模4可逆计数器设计预实验报告

    实验六:同步模4可逆计数器设计(综合设计性实验) -----用D触发器74HC74和74HC86设计制作一个模4可逆计数器 预习要点: 要求:实现以4为模的递增计数以及递减计数功能,(当X=0时,减1 ...

最新文章

  1. UITableView学习笔记
  2. oracle客户端三种连接,客户端连接ORACLE的几种方法
  3. Linux——VMware虚拟机安装CentOS步骤
  4. XML具有哪些特点?相对于HTML的优势
  5. 2.3绘制构造线与射线
  6. 台前与幕后的 5G 战争
  7. Shell脚本学习-阶段二十八-shell练习二
  8. Hadoop Partitioner 实战详解
  9. .Net Core WebApi集成JWT实现身份认证
  10. 根据pid查端口_PLC应用,3个PID控制实例讲解,想不会都难!
  11. 配置深度森林deep forest(2021)环境填坑
  12. 打包出来的 common.js/umd.js 是啥?
  13. 从 Web2 社交面临的挑战看,Web3 为何能够取而代之
  14. Excel读写工具类
  15. 添加遮罩css,添加遮罩层
  16. Ubuntu lightdm无法启动解决办法
  17. K8s NetworkPolicy与网络插件flannel、calico详细版
  18. matplotlib的常用的两种方式以及pylab
  19. 项目管理基础案例分析答案
  20. 升级后清理Ubuntu Grub引导菜单

热门文章

  1. 什么是WebAuthn:在Web上使用Touch ID和Windows Hello登录
  2. C++普通继承和虚继承详解
  3. 纯硬菜,大厂常用软件测试面试题二(附答案)
  4. Spring——Spring容器创建对象的方式
  5. 郑大第九届校赛正式赛(1818: squee_spoon and his Cube VI)
  6. 网络安全基础知识中间件简单介绍
  7. 指针引用和引用指针的区别
  8. 极坐标 c语言,牛顿 拉夫逊迭代法极坐标潮流计算C语言程序
  9. Pr学习DAY1-----认识Pr
  10. 小米拒绝权限_小米MIUI 12上手!流氓软件的克星,动画比肩iOS