存储器分配算法

news2024/11/25 4:58:58

1.设计目的与要求

1.1设计目的

        本设计的目的是使学生了解动态分区分配方式中使用的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现过程的理解。

1.2设计要求

        用C++语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程malloc()和回收过程free()。其中,空闲分区通过空闲分区链来管理;首次适应算法在进行内存分配时,系统优先使用空闲区低端的空间。回收时应注意相邻空闲分区的合并。

2.设计思想及系统平台

2.1设计思想

        1)数据结构:采用链式存储结构存储空闲分区链。空闲区的结构体包含分区号、首地址、分区大小、分配标志;链表结点的结构体包含空闲区结构体、front和next指针。

        2)首次适应算法:用p指针遍历整个链表,找到第一个空间大于等于请求空间的空闲区,将此空间分配给进程。若空闲区大于请求空间,则将低端空间分给进程后更新空闲区的大小。

        3)最佳适应算法:用p指针遍历整个链表,当找到第一个满足请求的空闲区时,记录此位置为最佳位置q,并将空闲区实际大小与请求大小的差值记为surplus,退出循环。然后再次遍历链表,每当有满足请求的空闲区时,若刚好满足请求,则将此位置分配给进程,算法结束;若大于,则比较二者的差值,如果此差值比原来的surplus要小,则更新surplus,同时修改q。遍历完链表后,如果存在最佳位置,则将该区域分配给进程,更新相关数据,算法结束。

        4)内存回收算法:判断回收分区与前后区的关系。如果前区为空闲状态,则合并,起始地址更改为前区的首地址,大小为二者之和;如果后区为空闲,合并后起始地址不变,大小为二者之和;如果前后区都是空闲的,三区合并,起始地址为前区的首地址,大小为三者之和。

2.2系统平台及使用语言

        CodeBlocks,C++

3.详细算法描述

1)首次适应算法

 

2)最佳适应算法

 

3)内存回收算法

 4.源程序清单

#include <iostream>
#include <stdlib.h>
#define FREE 0
#define BUSY 1
#define MAX_length 512
using namespace std;
//空闲区分表结构
struct freeArea
{
    int flag;//分配标志
    int size;
    int ID;
    int address;//首地址
};
struct node
{
	struct freeArea date;
	struct node *front;
	struct node *next;
};
struct node* head;//链表头指针
struct node* rear;//尾指针
void init()
{
	head=new struct node;
	rear = new struct node;
	head->front=NULL;
	head->next=rear;
	rear->front=head;
	rear->next=NULL;
	rear->date.address=0;
	rear->date.flag=FREE;
	rear->date.ID=FREE;
	rear->date.size=MAX_length;
}
//首次适应算法
int first_fit(int ID,int size)
{
	 struct node* temp=(struct node*)malloc(sizeof(struct node));
	 struct node *p=head->next;
	 temp->date.ID=ID;
	 temp->date.size=size;
	 temp->date.flag=BUSY;
	 //遍历空闲区链表
     while(p)
	 {
	    //空闲区且请求大小刚好满足
		if (p->date.flag==FREE && p->date.size==size)
		{
			p->date.flag=BUSY;
			p->date.ID=ID;
			return 1;
		}
		if (p->date.flag==FREE && p->date.size>size)
		{
		    //将temp插入到链表此位置上
			temp->next=p;
			temp->front=p->front;
			temp->date.address=p->date.address;
            p->front->next=temp;
            p->front=temp;
            p->date.address=temp->date.address+temp->date.size;
            p->date.size-=size;
            return 1;
		}
		p=p->next;
	}
	return 0;
}
//最佳适应算法
int best_fit(int ID,int size)
{
	int surplus;//记录可用内存与需求内存的差值
	struct node* temp=(struct node*)malloc(sizeof(struct node));
	struct node *p=head->next;
	temp->date.ID=ID;
	temp->date.size=size;
	temp->date.flag=BUSY;
	struct node *q=NULL;//记录最佳位置
	//找到第一个可用空间就分配给q
	while(p)
    {
		if (p->date.flag==FREE&&p->date.size>=size)
		{
			q=p;
			surplus=p->date.size-size;
			break;
		}
		p=p->next;
	}
	//继续遍历,找到更加合适的位置
	while(p)
	{
	    //刚好满足要求
		if (p->date.flag==FREE&&p->date.size==size)
		{
			p->date.flag=BUSY;
			p->date.ID=ID;
			return 1;
		}
		if (p->date.flag==FREE&&p->date.size>size)
		{
			if (surplus>p->date.size-size)
			{
				surplus=p->date.size-size;
				q=p;
			}
		}
		p=p->next;
	}
	//找到了最佳位置
	if (q!=NULL)
	{
        temp->next=q;
		temp->front=q->front;
		temp->date.address=q->date.address;
		q->front->next=temp;
		q->front=temp;
		q->date.size=surplus;
		q->date.address+=size;
		return 1;
	}
	else
	{
		return 0;
	}
}
//实现内存分配
int alloc(int choose)
{
    char ch;
    do{
        int ID,size;
        cout<<"作业号:";
        cin>>ID;
        cout<<"所需内存大小:";
        cin>>size;
        while (ID<=0 || size<=0)
        {
            cout<<"ERROR,请输入正确的ID和请求大小"<<endl;
            cout<<"作业号:";
            cin>>ID;
            cout<<"所需内存大小:";
            cin>>size;
        }
        switch(choose)
        {
            case 1:
                if(first_fit(ID,size))
                {
                    cout<<"分配成功!"<<endl;
                }
                else
                    cout<<"分配失败!"<<endl;
                break;
            case 2:
                if (best_fit(ID,size))
                {
                    cout<<"分配成功!"<<endl;
                }
                else
                    cout<<"分配失败!"<<endl;
                break;
        }
        cout<<"还要继续申请内存吗?Y/N"<<endl;
        cin>>ch;
    }while(ch!='N');
	return 1;
}
//内存回收
int free()
{
    int ID;
    cout<<"请输入需要回收的ID号:"<<endl;
    cin>>ID;
	struct node *p=head->next;
	while(p)
	{
	    //找到要回收的ID区域
		if (p->date.ID==ID)
		{
		    //释放p指向的内存
			p->date.flag=FREE;
			p->date.ID=FREE;
			//前空,合并
			if (p->front->date.flag==FREE&&p->next->date.flag!=FREE)
            {
                p->front->date.size+=p->date.size;
                p->front->next=p->next;
                p->next->front=p->front;
            }
			//后空
			if (p->front->date.flag!=FREE&&p->next->date.flag==FREE)
			{
				p->date.size+=p->next->date.size;
				if(p->next->next)
                {
                    p->next->next->front=p;
                    p->next = p->next->next;
                }
                else
                    p->next=p->next->next;
			}
			//前后都空
			if(p->front->date.flag==FREE&&p->next->date.flag==FREE)
            {
                p->front->date.size+=p->date.size+p->next->date.size;
                if(p->next->next)
                {
                    p->next->next->front=p->front;
                    p->front->next=p->next->next;
                }
                else
                    p->front->next=p->next->next;
            }
			break;
		}
		p=p->next;
	}
	cout<<"回收成功!"<<endl;
	return 1;
}
void display()
{
	cout<<"--------内存分配情况-------"<<endl;
	struct node *p=head->next;
	while(p)
	{
		cout<<"分区号:";
		if (p->date.ID==FREE)
            cout<<"FREE"<<endl;
		else
            cout<<p->date.ID<<endl;
		cout<<"起始地址:"<<p->date.address<<endl;
		cout<<"内存大小:"<<p->date.size<<endl;
		cout<<"分区状态:";
		if (p->date.flag==FREE)
			cout<<"空闲"<<endl;
		else
			 cout<<"已分配"<<endl;
		cout<<"---------------------------"<<endl<<endl;
		p=p->next;
	}
}
void menu()
{
    cout<<"------请输入要进行的操作------"<<endl;
    cout<<"      1、首次适应算法          "<<endl;
    cout<<"      2、最佳适应算法          "<<endl;
    cout<<"      3、内存回收              "<<endl;
    cout<<"      4、显示内存状况          "<<endl;
    cout<<"      0、退出                  "<<endl;
    cout<<"------------------------------"<<endl;
}
int main()
{
    int choose;
	init();
	do
	{
        menu();
        cin>>choose;
		switch(choose)
        {
            case 1:
                alloc(choose);
                break;
            case 2:
                alloc(choose);
                break;
            case 3:
                free();
                break;
            case 4:
                display();
                break;
            case 0:
                break;
            default:
                cout<<"输入错误,请重新输入!"<<endl;
                break;
        }
    }while(choose!=0);
	return 0;
}

实验报告:https://download.csdn.net/download/sjhdxpz/88212615

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/873250.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多表联合查询

1.创建student表 mysql> CREATE TABLE student ( -> id INT(10) NOT NULL UNIQUE PRIMARY KEY , -> name VARCHAR(20) NOT NULL , -> sex VARCHAR(4) , -> birth YEAR, -> department VARCHAR(20) , -> address VARCH…

【AWS 大赛】亚马逊云科技:2023 直冲云霄训练营入营考试报名与答题答案参考

目录 一、报名 &#xff08;1&#xff09;选择 “解决方案架构师-助理级” &#xff08;2&#xff09;未登录先注册账号 &#xff08;3&#xff09;登录 &#xff08;4&#xff09;报名 &#xff08;5&#xff09;报名成功 二、答题 &#xff08;1&#xff09;开始…

FreeRTOS(互斥信号量)

资料来源于硬件家园&#xff1a;资料汇总 - FreeRTOS实时操作系统课程(多任务管理) 目录 一、互斥信号量的定义与应用 1、互斥信号量的定义 2、互斥信号量的应用 3、简要了解递归互斥信号量 二、优先级翻转问题 1、运行条件 2、优先级翻转编程测试 三、互斥信号量的运…

[HDLBits] Exams/m2014 q3

Consider the function f shown in the Karnaugh map below. Implement this function. d is dont-care, which means you may choose to output whatever value is convenient. //empty

[HDLBits] Exams/2012 q1g

Consider the function f shown in the Karnaugh map below. Implement this function. (The original exam question asked for simplified SOP and POS forms of the function.) //

文本三剑客之grep命令和awk命令 1.0 版本

grep awk 1.grep命令1.1 基本格式1.2 常用选项 2.awk命令2.1 awk工作原理2.2 awk命令格式2.3 awk常用内置变量 1.grep命令 1.1 基本格式 grep [选项]… 查找条件 目标文件1.2 常用选项 选项功能 -m [ x ]匹配x次 后停止,x为具体数字-v取反 -i忽略字符大小写 -n显示匹配的 …

GrapeCity Documents for Excel, Java Edition Crack

GrapeCity Documents for Excel, Java Edition Crack 增加了对SpreadJS.sjs文件格式的支持&#xff1a; 更快地将大型Microsoft Excel文件转换为.sjs格式。 使用较小的占用空间保存导出的文件。 将Excel/SpreadJS功能导入SpreadJS/从SpreadJS导出。 从.sjs文件中压缩的JSON文件…

小程序发布注意事项

1、使用HBuildx的 发布 功能发布小程序&#xff0c;因为编译完的代码目录不是同一个 如果使用 运行 到小程序&#xff0c;最后发布的版本会显示”无法连接本地服务器“ 2、使用unicloud的云服务 uniCloud发行 | uni-app官网 阿里云的unicloud的话&#xff0c;使用request域名…

Docker启动、停止、删除容器的相关指令

关闭容器指令&#xff1a; docker stop name启动命令&#xff1a; docker start name删除容器&#xff1a; docker rm name 或 id查看所有容器id&#xff1a; docker ps -aq删除所有容器&#xff1a; docker rm docker ps -aq开启着的容器是不能被删除的。 查看容器信息&…

华为OD机试 - 最长连续子序列 - 双指针(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述备注 四、双指针1、双指针是什么&#xff1f;2、Java双指针算法适合解决哪些问题&#xff1f; 五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专…

GUI、多线程编程、网络编程简介

GUI、多线程编程、网络编程简介 文章目录 GUI简介什么是GUIGUI有什么用使用方法 多线程编程什么是多线程编程多线程编程有什么用提高程序的响应能力提高程序的性能实现异步编程并发数据访问和共享资源实现复杂的算法和任务分解 进行多线程编程的步骤 网络编程什么是网络编程网络…

day6 STM32时钟与定时器

STM32时钟系统的概述 概念 时钟系统是由振荡器&#xff08;信号源&#xff09;、定时唤醒器、分频器等组成的电路。 常用的信号有晶体振荡器和RC振荡器。 意义 时钟是嵌入式系统的脉搏&#xff0c;处理器内核在时钟驱动下完成指令执行&#xff0c;状态变换等动作&#xff…

迪瑞克斯拉算法

迪锐克斯拉算法 简单来说就是在有向图中&#xff0c;给定一个图中具体的出发点&#xff0c;从这个点出发能够到达的所有的点&#xff0c;每个点的最短距离是多少。到不了的点&#xff0c;距离则是正无穷。有向&#xff0c;无负权重&#xff0c;可以有环。 所以说&#xff0c;迪…

Linux 终端命令之文件浏览(4) head, tail

Linux 文件浏览命令 cat, more, less, head, tail&#xff0c;此五个文件浏览类的命令皆为外部命令。 hannHannYang:~$ which cat /usr/bin/cat hannHannYang:~$ which more /usr/bin/more hannHannYang:~$ which less /usr/bin/less hannHannYang:~$ which head /usr/bin/he…

流量日志分析--实操

[鹤城杯 2021]流量分析 <--第一道流量分析不难,主要就是布尔盲注的流量包分析,直接查看http请求包即可我们可以通过观察看到注入成功的响应长度不同,这里成功的为978字节,失败的994字节.不要问为什么.其实也可以直接判断.978的流量比994的少了非常多 显然就是成功的(因为这里…

云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初步使用(二)

前言&#xff1a; 在前面一篇文章云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初始安装&#xff08;一&#xff09;_华为cna_晚风_END的博客-CSDN博客 介绍了基于VMware虚拟机里嵌套部署华为云的云计算&#xff0c;不过仅仅是做到了在VRM的web界面添加计算节点…

高效数据传输:轻松上手将Kafka实时数据接入CnosDB

本篇我们将主要介绍如何在 Ubuntu 22.04.2 LTS 环境下&#xff0c;实现一个KafkaTelegrafCnosDB 同步实时获取流数据并存储的方案。在本次操作中&#xff0c;CnosDB 版本是2.3.0&#xff0c;Kafka 版本是2.5.1&#xff0c;Telegraf 版本是1.27.1 随着越来越多的应用程序架构转…

keil构建STM32工程并使用proteus仿真led点灯实验

STM32单片机与51单片机有很大区别&#xff0c;不仅结构上有很大差异&#xff0c;STM32更复杂一些&#xff0c;在操作上来说&#xff0c;STM32也要复杂很多&#xff0c;51单片机上手写代码&#xff0c;可以很直接操作引脚&#xff0c;但是STM32单片机在操作引脚之前需要作很多初…

学无止境·运维高阶⑤(LVS-DR 群集 配置Nginx负载均衡)

LVS-DR 群集 && 配置Nginx负载均衡 一、LVS-DR 群集1、相关配置环境2、在RS上配置并启动脚本2.1相关脚本2.2 启动脚本&#xff0c;另一台RS同样步骤 3、LVS-DR模式配置脚本4、测试 二、Nginx负载均衡1、安装Nginx并关闭相应设置2、向主机 node2&#xff0c;node3 写入内…

【第二阶段】kotlin函数引用

针对上篇传入函数参数我们也可以重新定义一个函数&#xff0c;然后在main中调用时传入函数对象 lambda属于函数类型的对象&#xff0c;需要把普通函数变成函数类型的对象&#xff08;函数引用&#xff09;&#xff0c;使用“&#xff1a;&#xff1a;” /*** You can edit, ru…