计算机操作系统_内存管理

article/2025/9/17 7:59:05

内存管理

设计程序模拟内存的动态分区内存管理方法。内存空闲区使用空闲分区表进行管理,采用最先适应算法从空闲分区表中寻找空闲区进行分配,内存回收时不考虑与相邻空闲区的合并。
假定系统的内存共640K,初始状态为操作系统本身占用40K。

t1 时刻,为作业A、B、C分配80K、60K、100K、的内存空间;
t2 时刻作业B完成;
t3 时刻为作业D分配50K的内存空间;
t4 时刻作业C、A完成;
t5 时刻作业D完成。

要求编程序分别输出t1、t2、t3、t4、t5时刻内存的空闲区的状态。

流程图:
在这里插入图片描述

数据结构定义:

//进程PCB类型的描述
struct PCB
{char name;    //进程名int address;   //进程分区起止int len;      //进程所占分区长度
};
struct PCB PCBelem[maxPCB];//进程占用内存表
//分区类型的描述
struct Part
{int address;	//空闲分区起始地址int len;		//空闲分区大小
};
struct Part Partelem[maxPart]; //空闲分区表

主要变量说明:

int length = 640 ;		//系统有 640 KB 的空闲
int fnum = 0;			//记录总的分区数量
int jnum = 0;			//记录总的进程数量
int leng = 0;			//临时变量

函数说明:

void init4IOS(int tem) 		//为操作系统分配40k内存
int getTagByPcb(char name) 	//判定输入的进程是否存在以及位置
void request()				//进程分配请求
void getPrint()				//打印空闲分区
void jcPrintf()				//打印进程
void release()				//回收指定进程内存

关键点叙述:

(1) 内存结构的建立及表示
在这里插入图片描述
分别建立进程占用内存表和空闲分区表,由于进程和空闲分区的所有属性值不一样,所以需要分别建表,它们之间起始地址是连续的,逻辑上形成一整块内存。

(2) 进程请求分配
在这里插入图片描述
当进程提出内存分配请求以后,首先需要做的是在空闲分区表当中寻找一个单独的,足够请求进程分配的内存空间。注意,寻求该空间需要从内存低址开始寻找,这样有利于保护高址大块内存,当然,缺点就是会产生较多的碎片内存,这些内存难以被利用。(本程序未涉及相邻空闲空间的合并,以及内存空间的紧凑)若存在这样一个空间,则从该空间当中划出请求进程所需的内存大小,将该内存块(含有起始地址等信息的结构体结点)存入进程占用内存表当中,同时,对于被划分的内存空间,需要修改其起始地址,达到逻辑上的合理。值得一提的是,若内存分配以后,被划分内存空间大小为0,则需要除去该条记录(移除(覆盖)空闲分区表)。

(3)回收进程
当对指定进程提出回收要求时,会产生两个反应,一是会对空闲分区表插入一块内存,用以表示被回收内存的空闲已空闲出来;二是对于被回收的进程,不应该出现在进程占用表当中,所以应当将其移除进程占用表。
对于以上两个操作的实现:对空闲分区表插入空闲内存时,需要从高址内存空间开始对比插入内存空间的大小,当出现内存空间的起始地址小于插入内存空间的起始地址时停止对比查找,将其后的内存空间均向后移动一位,以腾出一个位置用于插入需要插入的空闲内存空间,这样在物理结构上也就合理了。除去被回收的进程,思想与上类似,找到该进程以后,将该进程以后的结点均向前移动一位,末尾指向相应减一,除去被回收的进程目的在于避免对同一进程进行重复回收。

存在问题
模拟内存管理所实现效果简单,与真实内存分配存在很大差异。

改进:
(1) 实现相邻空闲空间的合并
(2) 内存空间紧凑
(3) 其他优化

个人总结:
1、 本程序编写完成以后,初步理解内存管理过程。程序实现的功能较为简单,没有考虑相邻空闲分区的合并,以及碎片空间的紧凑整理等操作。
2、越努力,越幸运!_

程序效果图(部分):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整代码:

#include "stdio.h"
#include "Windows.h"#define  maxPCB 100   //定义最大PCB结点数
#define  maxPart 100  //定义最大分区//进程PCB类型的描述
struct PCB
{char name;    //进程名int address;  //进程分区起止int len;      //进程所占分区长度
};
struct PCB PCBelem[maxPCB];//进程占用内存表//分区类型的描述
struct Part
{int address;	//空闲分区起始地址int len;		//空闲分区大小
};
struct Part Partelem[maxPart];//空闲分区表int length = 640 ;	//系统有 640 KB 的空闲
int fnum = 0;		//记录总的分区数量
int jnum = 0;		//记录总的进程数量struct Part part;	//公共使用临时结点(分区)
struct PCB pcb;		//公共使用临时结点(进程)//为操作系统分配40k内存
void init4IOS(int tem)
{length = length - tem;	//剩余系统空闲空间减少part.address = 0 + 40;	//操作系统占用,空闲内存从40开始part.len = length;		//空闲内存大小Partelem[fnum] = part;	//存入空闲分区表fnum ++;				//分区数增加
}//判定输入的进程是否存在以及位置
int getTagByPcb(char name)
{int i;for(i = 0; i < jnum; i ++){if(name == PCBelem[i].name){return i;}	}printf("\n\t\t找不到进程名%c,请重新输入!\n",name);	 return -1;
}//进程分配请求
void request()
{char c = 0;while(true){printf("\n\t\t请输入请求内存进程 名称:");fflush(stdin);//清空缓冲区scanf("%c",&pcb.name);//检查是否已存在进程for(int j = 0; j < jnum; j++){if(PCBelem[j].name == pcb.name){printf("\n\t\t进程 %c 已存在,可尝试输入其他名称,也可以先回收该进程!\n",pcb.name);return;}}printf("\n\t\t\t\t   长度:");fflush(stdin);//清空缓冲区scanf("%d",&pcb.len);length = length - pcb.len;	//减去相对应的操作系统剩余空闲空间	if(length <= 0){if(length == 0){printf("\n\t\t警告:系统资源已经全部分配!\n");			}else{length = length + pcb.len;	//分配失败将内存换回去,以免溢出printf("\n\t\t未找到合适空间或者系统资源不足!\n");	return;}}//如果符合分配条件,进行分配for(int i = 0; i < fnum; i++){//寻找一个可以分配的空间if(pcb.len <= Partelem[i].len){//改变进程占用地址pcb.address = Partelem[i].address;//保存该进程PCBelem[jnum++] = pcb;//对空闲分区进行划分Partelem[i].address = Partelem[i].address + pcb.len;Partelem[i].len = Partelem[i].len - pcb.len;break;//关键作用(从低址找到一个空间就可以了,没必要再往后找了)}			}//除去分配后空闲空间为0的记录if(Partelem[i].len == 0){int leng = i;//进行前移覆盖while(leng != fnum){part.address = Partelem[leng+1].address;part.len = Partelem[leng+1].len;Partelem[leng] = part;leng++;}//分区数减少fnum--;}printf("\n\t\t是否要继续输入进程?(Y/y) 是/(N/n) 否:");fflush(stdin);c = getchar(); fflush(stdin);if(c=='N'||c=='n'){break;}}
}//打印空闲分区
void getPrint()
{printf("\t\t----------------------空闲分区 begin----------------------\n");int j = 1;for (int i = 0;i < fnum; i ++){printf("\n\t\t第%d块空闲内存 起始地址为%d,容量为%d\n",j,Partelem[i].address,Partelem[i].len);j ++;}printf("\n\t\t----------------------空闲分区  end ----------------------\n"); 
}//打印进程
void jcPrintf()
{printf("\n\t\t名称\t起始地址\t大小\n");for(int i = 0 ; i < jnum; i++){printf("\n\t\t%2c\t%4d\t\t%d KB\n",PCBelem[i].name,PCBelem[i].address,PCBelem[i].len);}
}//回收指定进程内存
void release()
{int i = 0;char name;printf("\n\t\t请输入想要回收的进程名称:");fflush(stdin);//清空缓冲区scanf("%c",&name);if(getTagByPcb(name) == -1){printf("\n\t\t该进程不存在或者已经被回收!\n");return;}printf("\n\t\t正在回收%c的内存:",name);for(int j = 0; j < 15; j++){printf("▊");Sleep(200);}printf(" 完成 \n");//for循环寻找该进程for(i = fnum; i >= 0; i --){int leng = fnum;if(PCBelem[getTagByPcb(name)].address > Partelem[i-1].address || i == 0){//while循环为该进程腾出一个位置while(leng != i){part.address = Partelem[leng-1].address;part.len = Partelem[leng-1].len;Partelem[leng] = part;leng--;}break;//关键(从高址往前找到一个空间就可以了,没必要再往前找了)}		}//系统空闲空间对应增加length = length + PCBelem[getTagByPcb(name)].len;//使用公共的结点记录即将产生的空闲空间part.address = PCBelem[getTagByPcb(name)].address; part.len = PCBelem[getTagByPcb(name)].len;//将该结点存入之前腾出的位置Partelem[i] = part;//分区数增加fnum ++;//对进程占用内存表进行调整,除去被回收进程int leng = getTagByPcb(name);//进行前移覆盖while(leng != jnum){pcb.name = PCBelem[leng+1].name;pcb.address = PCBelem[leng+1].address;pcb.len = PCBelem[leng+1].len;PCBelem[leng] = pcb;leng++;}//进程数减少jnum--;
}void main()
{char tem = 0;int OSsize = 40;int b = 1, k;//为操作系统分配内存init4IOS(OSsize);while (b){system("cls");printf("\n\n\t\t操作系统内存分配\n\n");printf("\t\t已为操作系统分配了 40 KB 内存\n",tem);printf("\n\t\t ----------------------------\n");printf("\t\t|1.... 请求分配内存           |\n");printf("\t\t|2.... 输出空闲分区           |\n");printf("\t\t|3.... 强制进程结束           |\n");printf("\t\t|4.... 输出进程信息           |\n");printf("\t\t|0.... 退出                   |\n");printf("\t\t ----------------------------\n\n");printf("\t\t当前操作系统空闲内存:%d KB\n",length);		printf("\n\t\t请选择:");fflush(stdin);//清空缓冲区scanf("%d", &k);switch (k){	case 1: request();       break;case 2: getPrint();	     break;case 3: release();       break;case 4: jcPrintf();      break;case 0:	b = 0;           break;default:printf("\n\t\t输入无效!\n");break;}if (b != 0)  { printf("\n\t\t"); system("pause"); }}
}

如有错误,欢迎指正!


http://chatgpt.dhexx.cn/article/tuwPDo8E.shtml

相关文章

关于计算机中内存的分类

**关于计算机中内存的分类&#xff08;栈区&#xff0c;堆区&#xff0c;静态区&#xff09;**1、栈区&#xff1a;主要用于函数的存储&#xff0c;从主函数开始&#xff0c;依次加入所引用的主函数。新加入的函数优先运行&#xff08;类似于数据结构的栈&#xff09;当一个函数…

计算机内存数值存储方式进制

进制概念 进制也就是进位制&#xff0c;是人们规定的一种进位方法。对于任何一种进制&#xff0c;x进制表示某一位置上的数运算时是逢x进一位。十进制是逢十进一、十六进制是逢十六进一、二进制是逢二进一。 各进制数表示 八进制是逢8进1&#xff0c;所以到8的时候向前进一位…

计算机内存结构!

变量的三大特点&#xff1a; 数据类型、作用域、存储类型 计算机的三大组成: 1.CPU 2.内存 3.硬盘 内存与硬盘的区别&#xff1a; 1.内存中保存动态数据&#xff0c;硬盘中保存静态数据。 2.断电后内存中的数据丢失&#xff0c;硬盘中的数据不会丢失。 3.执行程序时&#xff0c…

内存管理计算

一、补充概念 为了保证CPU执行指令时可正确访问存储单元&#xff0c;需将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址&#xff0c;这一过程称为地址映射。地址映射一般是由硬件完成的&#xff1b;页表项的相关状态位由硬件确定。 最佳适应算法&#xff08;空闲内…

计算机内存和磁盘的关系

计算机内存和磁盘的关系 前言 上篇文章详细讲了计算机内存的物理结构&#xff0c;逻辑结构以及在内存的基础上理解几种常见的数据结构。但是&#xff0c;计算机系统出了内存之外&#xff0c;还有一个非常重要的硬件&#xff0c;那就是磁盘。他们都是用于计算机存储&#xff0…

电脑硬件——内存

内存是一台电脑CPU与硬盘间进行数据传输的中转站&#xff0c;内存会影响着电脑的稳定性&#xff0c;不稳定的内存可能会导致蓝屏、黑屏、死机甚至电脑无法亮机等故障。 内存的作用&#xff1a; 在我们的电脑工作时&#xff0c;CPU和硬盘之间会无时不刻地进行大量的数据交换&am…

计算机(二):计算机存储系统(内存、外存)。

前言&#xff1a;我总结了汇编语言课本和通信书上的知识点给大家呈现。 一、计算机存储系统&#xff08;文解&#xff09;&#xff1a; 存储分为&#xff1a;内存&#xff08;内部存储器&#xff09;、外存&#xff08;外部存储器&#xff09;。 内存分为&#xff1a;CPU上的寄…

计算机内存介绍

我们这里说的内存啊&#xff0c;其实就是说的我们电脑里面的内存条&#xff0c;所以嘞&#xff0c;内存就是内存条&#xff0c;数据要放在这上面才能被cpu读取从而做运算&#xff0c;还有硬盘&#xff0c;就是电脑中的C盘啥的&#xff0c;一个程序需要运行的话需要向内存申请一…

计算机的内存

1.内存的物理机制 内存和CPU一样&#xff0c;都是由大量引脚构成的集成电路&#xff0c;内存大致分为这几类&#xff1a;1.ROM:只能进行读取&#xff1b;2.DRAM&#xff1a;需要经常刷新就能进行保存数据的可被读取和写入的内存&#xff1b;3.SRAM&#xff1a;不需要经常刷新就…

【操作系统】计算机内存管理

文章目录 1.内存管理目标rom-ram2.计算机内存的惰性分配3.内存管理-分而治之思想4.内存不够的情况处理5.内存扩容swap配置实战6.Linux的free命令详解7.Linux的top命令详解 1.内存管理目标rom-ram &#xff08;1&#xff09;为啥要做内存管理 计算机不可能所以用户进程和系统所…

计算机|内存知多少

​1、硬件层面 内存就是名为内存IC的电子元件。&#xff08;IC&#xff0c;集成电路&#xff0c;内存也是一种集成电路&#xff09; 内存IC的引脚配置 那这个内存IC能存多少数据&#xff1f; 数据信号引脚有D0~D7一共8个&#xff0c;表示一次输入输出8位数据&#xff08;一个字…

计算机底层知识之内存

❝ 渔夫出海前&#xff0c;并不知道鱼在哪里&#xff0c;可是他们还是选择出发&#xff0c; 因为他们相信&#xff0c;一定会满载而归。人生很多时候&#xff0c;是「选择了才有机会&#xff0c;是相信了才有可能」。 -- 「稻盛和夫」 ❞ 大家好&#xff0c;我是「柒八九」。 …

计算机基础之内存

目录 1.什么是内存2.内存的物理结构3.内存的使用4.数据在内存中为什么用二进制表示5.二进制的补码 1.什么是内存 内存是与cpu沟通的桥梁&#xff0c;计算机中所有程序的运行都要依靠内存&#xff0c;内存对计算机的影响非常大&#xff0c;内存又被称为主存&#xff0c;作用就是…

计算机基础- -认识内存

计算机基础- -认识内存 文章目录 计算机基础- -认识内存一、什么是内存二、内存的物理结构1.内存的读写过程2.内存的现实模型 三、内存的使用1.指针2.数组是内存的实现3.栈和队列4.链表5.二叉树 一、什么是内存 内存(Memory) 是计算机中最重要的部件之一&#xff0c;它是程序与…

电脑内存介绍(精心整理)

内存是电脑的主要硬件之一&#xff0c;主要用于存储和交换正在运行的程序和数据。简单的说就是&#xff0c;断电之后&#xff0c;内存存储的数据就会消失。所以我们常用的软件需要安装在硬盘等外存设备里&#xff0c;打开游戏或者软件时&#xff0c;就需要把他们调出到内存中运…

四大CPU架构的区别

我们目前使用比较多的架构有&#xff1a;ARM、RISC-V、MIPS&#xff0c;X86等等。其实还有一些指令的&#xff0c;但是其他的指令都是比较小众&#xff0c;只在专业的领域使用。 我们目前使用比较多的架构有&#xff1a;ARM、RISC-V、MIPS&#xff0c;X86等等。其实还有一些指…

四大CPU架构区别

我们目前使用比较多的架构有&#xff1a;ARM、RISC-V、MIPS&#xff0c;X86等等。其实还有一些指令的&#xff0c;但是其他的指令都是比较小众&#xff0c;只在专业的领域使用。 ARM架构是一个32位精简指令集处理器架构&#xff0c;其广泛地使用在许多嵌入式系统设计。它主要从…

Linux 查看CPU架构及内核版本

涉及arch命令和/proc/version文件 1 查看CPU架构 有些软件的安装需要和CPU架构相匹配&#xff0c;如JDK等等&#xff0c;所以需要确定主机的CPU架构类型。可使用命令arch查看Linux系统的CPU架构&#xff0c;如下&#xff1a; arch2 查看内核版本 文件/proc/version中包含系统…

如何查看手机的CPU架构

几款专门获取手机设备信息的App&#xff1a; 通过这些App&#xff0c;你能看到你的安卓手机很多核心底层的信息&#xff0c;对于开发者而言&#xff0c;这些信息对于开发App时的写代码或者debug何其重要&#xff01; 这些App都能查看像CPU架构、GPU、传感器、温度、存储、电池…

Android CPU架构

Android CPU架构有&#xff1a;arm64-v8a、armeabi-v7a、armeabi、x86 CPU架构 1&#xff09;arm64-v8a 第8代、64位、ARM处理器 包含AArch32、AArch64两个执行状态对应32、64bit 支持arm64-v8a、armeabi-v7a、armeabi 2&#xff09;armeabi-v7a 第7代、ARM处理器 …