操作系统:主存储器空间的分配和回收

2023-11-11

主存储器空间的分配和回收 预习报告

一、实验内容

主存储器空间的分配和回收。

二、实验目的

一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能合理地分配和使用这些存储空间。当用户提出申请存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,找出足够的空闲区域分配给申请者。当作业撤离或主动归还主存资源时,则存储管理要收回作业占用的主存空间或归还部分主存空间。主存的分配和回收的实现与主存储器的管理方式有关的,通过本实验帮助学生理解在可变分区管理方式下应怎样实现主存空间的分配和回收。

三、实验原理

模拟在可变分区管理方式下采用最先适应算法实现主存分配和回收。

(1)可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。例如:

操作系统

作业1

作业3

空闲区

作业2

空闲区

0

5k

10k

14k

26k

32k

512k

 

为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:

起    址

长    度

状      态

第一栏

14 K

12 K

未 分 配

第二栏

32 K

96 K

未 分 配

M

M

M

M

其中,起址——指出一个空闲区的主存起始地址。

      长度——指出从起始地址开始的一个连续空闲的长度。

      状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区。

 (2) 当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。

(3) 采用最先适应算法分配主存空间。

按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。当空闲区大于需要量时,一部分用来装入作业,另一部分仍为空闲区登记在空闲区说明表中。

由于本实验是模拟主存的分配,所以把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。

(4) 当一个作业执行结束撤离时,作业所占的区域应该归还,归还的区域如果与其它空闲区相邻,则应合成一个较大的空闲区,登记在空闲区说明表中。

(5) 请按最先适应算法设计主存分配和回收的程序。假设初始时主存中没有作业,现按下面序列进行内存的申请与释放:

作业1申请300K,作业2申请100K,作业1释放300K,作业3申请150K,

作业4申请30K, 作业5申请40K, 作业6申请60K, 作业4释放30K。    

请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。

  主存储器空间的分配和回收

一、实验内容

主存储器空间的分配和回收。

二、实验目的

一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能合理地分配和使用这些存储空间。当用户提出申请存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,找出足够的空闲区域分配给申请者。当作业撤离或主动归还主存资源时,则存储管理要收回作业占用的主存空间或归还部分主存空间。主存的分配和回收的实现与主存储器的管理方式有关的,通过本实验帮助学生理解在可变分区管理方式下应怎样实现主存空间的分配和回收。

三、实验原理

模拟在可变分区管理方式下采用最先适应算法实现主存分配和回收。

(1)可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。例如:

操作系统

作业1

作业3

空闲区

作业2

空闲区

0

5k

10k

14k

26k

32k

512k

为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:

起    址

长    度

状      态

第一栏

14 K

12 K

未 分 配

第二栏

32 K

96 K

未 分 配

M

M

M

M

其中,起址——指出一个空闲区的主存起始地址。

      长度——指出从起始地址开始的一个连续空闲的长度。

      状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区。

 (2) 当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。

(3) 采用最先适应算法分配主存空间。

按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。当空闲区大于需要量时,一部分用来装入作业,另一部分仍为空闲区登记在空闲区说明表中。

由于本实验是模拟主存的分配,所以把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。

(4) 当一个作业执行结束撤离时,作业所占的区域应该归还,归还的区域如果与其它空闲区相邻,则应合成一个较大的空闲区,登记在空闲区说明表中。

(5) 请按最先适应算法设计主存分配和回收的程序。假设初始时主存中没有作业,现按下面序列进行内存的申请与释放:

作业1申请300K,作业2申请100K,作业1释放300K,作业3申请150K,

作业4申请30K, 作业5申请40K, 作业6申请60K, 作业4释放30K。    

请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。

四、算法流程图

1.最先适应分配算法流程图

 

2.归还主存时的回收算法流程图。

 

五、源程序及注释

//主存储器空间的分配和回收

#include<iostream>

#include<algorithm>

using namespace std;



struct Area{

    int length; //长度

    int start;  //起址

    int end;   //终址 = 起址+长度

    int num;  //作业编号

};



Area OS_busy[100];  //工作区域区域

Area OS_free[100];  //空闲区域队列

int countBusy = 3; //工作区域的数量

int countFree = 2; //空闲区域的数量

int maxLength = 512; //最大工作长度

int osLength = 5;//操作系统工作长度



//自定义规则,对区域根据起始地址进行排序

bool Compare(Area a,Area b) {

    return a.start < b.start;

}



//对工作的初始化的函数,防止函数的重复书写

void initBusy(int t_start,int t_length,int t_num) {

    OS_busy[t_num].start = t_start;

    OS_busy[t_num].length = t_length;

    OS_busy[t_num].end = t_start + t_length;

    OS_busy[t_num].num = t_num;

}



//显示工作区域信息

void showBusy() {

    cout << "工作区域如下:" << endl;

    cout << "---------------------------------" << endl;

    cout << "序号\t 作业\t起址\t长度\t终址 " << endl;

    for (int i = 1; i <= countBusy; i++)

    {

        cout << i << "\t";

        cout <<"作业" << OS_busy[i].num << "\t";

        cout << OS_busy[i].start << "k " << "\t ";

        cout << OS_busy[i].length << "k " << "\t ";

        cout << OS_busy[i].end << "k ";

        cout << endl;

    }

    cout << "---------------------------------" << endl;

}



//显示空闲区域信息

void showFree() {

    cout << "\n空闲区域如下:" << endl;

    cout << "---------------------------------" << endl;

    cout << "序号\t 作业\t起址\t长度\t终址 " << endl;

    for (int i = 1; i <= countFree; i++)

    {

        cout << i << "\t";

        cout << "作业" << OS_free[i].num << "\t";

        cout << OS_free[i].start << "k " << "\t ";

        cout << OS_free[i].length << "k " << "\t ";

        cout << OS_free[i].end << "k ";

        cout << endl;

    }

    cout << "---------------------------------" << endl;

}



//初始化区域

void init() {

    //初始化主存中作业情况

    initBusy(5, 5, 1);

    initBusy(26, 6, 2);

    initBusy(10, 4, 3);



    sort(OS_busy + 1, OS_busy + 1 + countBusy, Compare);//利用自己建立的规则对工作序列按照起址升序排列

    initBusy(0, 5, 0);

    int t_count = 0;

    for (int i = 0; i < countBusy; i++)

    {

        if (OS_busy[i].end < OS_busy[i + 1].start) {

           t_count++;

           //有空闲区域

           OS_free[t_count].start = OS_busy[i].end;

           OS_free[t_count].length = OS_busy[i + 1].start - OS_busy[i].end;

           OS_free[t_count].end = OS_busy[i + 1].start;

           OS_free[t_count].num = t_count;

        }

    }



    if (OS_busy[3].end < maxLength) {

        t_count++;

        OS_free[t_count].start = OS_busy[countBusy].end;

        OS_free[t_count].length = maxLength - OS_busy[countBusy].end;

        OS_free[t_count].end = maxLength;

        OS_free[t_count].num = t_count;

    }

    showBusy();

    showFree();

    return;

}



//分配任务

void Distri() {

    cout << "开始分配任务:" << endl;

    int tempCount = countBusy + 1;

    cout << "请输入作业" << tempCount << "的长度" << endl;

    cin >> OS_busy[tempCount].length;

    OS_busy[tempCount].num = tempCount;



    bool flag = 0;



    for (int i = 1; i <= countFree; i++)

    {

        if (OS_free[i].length >= OS_busy[tempCount].length) {

           //长度合适 可以分配

           //添加工作区

           OS_busy[tempCount].start = OS_free[i].start;

           OS_busy[tempCount].end = OS_busy[tempCount].start + OS_busy[tempCount].length;



           //修改空闲区

           OS_free[i].start += OS_busy[tempCount].length;

           OS_free[i].length -= OS_busy[tempCount].length;



           if (OS_free[i].length == 0) {

               countFree--;



               for (int j = i; j<= countFree; j++)

               {

                   OS_free[j] = OS_free[j + 1];

               }

           }

           flag = 1;

           break;

        }

    }

    if (flag) {

        //分配成功

        countBusy++;

        cout << "分配成功!起始地址为:" << OS_busy[tempCount].start << endl;

        sort(OS_busy + 1, OS_busy + 1 + countBusy, Compare);

        cout << "分配后主存情况如下:" << endl;

        showBusy();

        showFree();

        system("pause");

    }

    else {

        cout << "分配失败!" << endl;

        system("pause");

    }

    return;

}



void Release() {

    int choice;

    cout << "请输入要释放的作业编号:";

    cin >> choice;

    bool flag1 = 0; //标志是否存在与内存

    int pos;       //所在位置

    for (int i = 1; i <= countBusy; i++)

    {

        if (OS_busy[i].num == choice) {

           flag1 = 1;

           pos = i;

           break;

        }

    }

    if (flag1 == 0) {

        cout << "主存中不存在此作业!" << endl;

        cout << "=========================" << endl;

        return;

    }

    bool flag2 = 0; //检查是否有下临界的空闲区

    for (int i = 1; i <= countFree; i++)

    {

        if (OS_busy[pos].end == OS_free[i].start) {

           flag2 = 1;

           OS_free[i].start = OS_busy[pos].start;

           OS_free[i].length += OS_busy[pos].length;

           OS_free[i].num = i;

           break;

        }

    }

    bool flag3 = 0; //检查是否有上临界的空闲区

    for (int i = 1; i <= countFree; i++)

    {

        if (OS_busy[pos].start == OS_free[i].end) {

           flag3 = 1;

           if (flag2 == 1) {

               OS_free[i].length += OS_free[i+1].length;

               OS_free[i].end += OS_free[i+1].end;

               OS_free[i].num = i;



               countFree--;



               for (int j = i+1; j <= countFree; j++)

               {

                   OS_free[j] = OS_free[j + 1];

               }

           }

           if (flag2 == 0) {

               //没有下相邻空闲区域

               OS_free[i].length += OS_busy[pos].length;

               OS_free[i].end = OS_busy[pos].end;

               OS_free[i].num = i;

           }

           break;

          

        }

    }

    if (flag2 == 0 && flag3 == 0) {

        //表示无相邻空闲区 新建空闲区

        countFree++;

        OS_free[countFree].length = OS_busy[pos].length;

        OS_free[countFree].end = OS_busy[pos].end;

        OS_free[countFree].start = OS_busy[pos].start;

        OS_free[countFree].num = countFree;

        sort(OS_free + 1, OS_free + 1 + countFree, Compare);

    }

    OS_busy[pos].start = 0x3f3f3f;

    sort(OS_busy + 1, OS_busy + 1 + countBusy, Compare);

    countBusy--;

    showBusy();

    showFree();

    return;

}



//主程序

int main() {

    init();

    int choice;

    while (true) {

        cout << "请输入您的操作:";

        cout << "1.分配作业  2.回收作业  3.退出程序" << endl;

        cin >> choice;

        if (choice == 1) {

           //分配作业

           Distri();

        }

        else if (choice == 2) {

           //回收作业

           Release();

        }

        else {

           exit(0);

        }

    }

}

六、打印的程序运行时初值和运行结果

1.初始状态

 

2. 作业1申请300K

 

3.作业2申请100K

 

4.作业1释放300K

 

5.作业3申请150K

 

6.作业4申请30K

 

7.作业5申请40K

 

8.作业6申请60K

 

9.作业4释放30K

 

七、实验小结

1.对自己本次实验收获进行小结。

本次实验算法实现的难点在于作业分配与回收的设计。在作业装入主存时由于作业的长度和空闲区的长度很可能不一样,这样很可能导致每个作业按页装入主存中时,还存在一定的空间区域,利用算法将这些区域再分割成更小的区域,在释放作业时,若有相邻的空闲区,则将其合并。

2.如果在要申请一个100K的作业空间,能否满足?

答:如图,不能,此时主存中已经没有长度为100k的空间 若此时强行分配,会导致分配失败。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

操作系统:主存储器空间的分配和回收 的相关文章

随机推荐

  • 基于SDF的抽骨架之散点图(Projected points)

    span style font family none background color rgb 255 255 255 1 SDF 形状直径函数 span span style font family none background co
  • element-ui表格实现跨页多选

    1 在type selection 的column中添加reserve selection属性 以保留当前所选数据
  • Arduino实验十八 旋转编码器实验

    学习任务 学会使用旋转编码器 关注微信公众号 爱享生活科技 color FF0000 关注微信公众号 爱享生活科技 关注微信公众号 爱享生活科技 组件 Arduion主板 旋转编码器 I2CLCD1602液晶显示器 杜邦线 面包板 下图是旋
  • JS base64与utf8相互转换

    utf8Url utf8编码字符串 let base64URL Buffer from utf8Url toString base64 base64UR base64编码字符串 let utf8Url Buffer from base64U
  • 李开复创业了

    上周五9月4日 一看新闻 头条就是 李开复离开Google 准备创业 等新闻 我吓了一跳 李开复作为全球一流企业的高管 居然都辞职不干了 记得李开复在大学生心目中一直都是导师的身份 他为我们写了7封信了 教导着中国的新生代怎么面对困难 积极
  • 基于Udacity模拟器的端到端自动驾驶决策

    1 端到端自动驾驶决策 端到端自动驾驶决策的输入为车辆的感知信息 如摄像头信息 输出为车辆的前轮转角和摄像头等信息 如上图所示 为英伟达公司的端到端自动驾驶决策框架 其CNN网络如下图所示 其中包括一个归一化层 5个卷积层和3个完全的全连接
  • oracle获取某一天某个时间点

    例如每个月12号18点时间 trunc add months last day FBizDate 1 12 18 24
  • Python之第九章 组织文件

    一 shutil模块 shutil 或称为 shell 工具 模块中包含一些函数 让你在 Python 程序中复制 移动 改名和删除文件 要使用 shutil 的函数 首先需要 import shutil 1 复制文件和文件夹 gt gt
  • Linux下Gcc生成和使用静态库和动态库详解(转)

    原文地址 http my chinaunix net space php uid 23592843 do blog id 223539 一 基本概念 1 1什么是库 在windows平台和linux平台下都大量存在着库 本质上来说库是一种可
  • Pip源地址和.condarc(conda 配置文件)

    1 pip源 清华源地址 https pypi tuna tsinghua edu cn simple 阿里源地址 https mirrors aliyun com pypi simple 官方源地址 https pypi python o
  • 使用动态链接库的好处

    1 可以采用多种编程语言来编写 2 增强产品的功能 3 提供二次开发的平台 4 简化项目管理 5 可以节省磁盘空间和内存 6 有助于资源的共享 7 有助于实现应用程序的本地化 更多内容请看C C 动态链接库 DLL 详解 来源 孙鑫 VC
  • 真正的人工智能支付时代已经来临

    我国就开始掀起人工智能热潮 随着互联网推动数字化的普及以及计算能力的进一步提高 真正的人工智能时代已经来临 刷脸支付基于人脸识别这种人工智能技术 已经广泛应用于商超 零售 医疗 景区等各大生活场景 刷脸支付做为2019年的迸发元年 嗅到商机
  • vue:分页跳转页面详情,返回记住当前点击第几页

    背景 项目中从列表页跳转到详情页返回的时候会默认跳转到分页的第一页 不利于用户的体验 所以需要返回到当前页 实现方法 方法一 Vue2提供了组件级路由钩子函数 分别是beforeRouteEnter beforeRouteUpdate be
  • 解决gbk转utf8乱码

    解决GBK字符转UTF 8乱码问题 gbk转utf 8 奇数中文乱码 一 乱码的原因 gbk的中文编码是一个汉字用 2 个字节表示 例如汉字 内部 的gbk编码16进制的显示为c4 da b2 bf utf 8的中文编码是一个汉字用 3 个
  • opencv VS 环境搭建 读取显示图像 访问像素

    1 opencv 下载 Releases OpenCV 这两个都可以 一个是安装包 一个是压缩吧 安装包也就是个解压的东西 没啥区别 若下载速度慢考虑翻墙 不然就等等 解压之后 source是opencv源码 build 是opecv 的源
  • SQL Server数据的Aes加密存入与解密取出

    最近在做winfrom的毕设 边做边学 由于这个东西折磨了我一天 所以写一篇学习心得记录一下这天的收获 顺便吐槽一下这个气人代码 由于本人是个菜鸡所以如果有缺陷或不足的地方欢迎大佬指出 另 项目环境为 VS2022 SQL Server 2
  • python绘制频谱图_使用python进行傅里叶FFT-频谱分析详细教程

    目录 一 一些关键概念的引入 1 离散傅里叶变换 DFT 2 快速傅里叶变换 FFT 3 采样频率以及采样定理 4 如何理解采样定理 二 使用scipy包实现快速傅里叶变换 1 产生原始信号 原始信号是三个正弦波的叠加 2 快速傅里叶变换
  • 关于plt.imshow()显示彩图问题

    https blog csdn net cnnmena article details 79613531 转载于 https www cnblogs com weststar p 11539800 html
  • fabric.js 怎么将 Group 中的元素包装在一个容器元素中,然后绑定事件到group元素的某个子元素上...

    你可以这样做 在 Group 中添加一个容器元素 比如一个矩形或圆形 将 Group 中的其他元素添加到容器元素中 使用 Group 对象的 on 方法绑定事件到容器元素上 例如 创建一个 Group var group new fabri
  • 操作系统:主存储器空间的分配和回收

    主存储器空间的分配和回收 预习报告 一 实验内容 主存储器空间的分配和回收 二 实验目的 一个好的计算机系统不仅要有一个足够容量的 存取速度高的 稳定可靠的主存储器 而且要能合理地分配和使用这些存储空间 当用户提出申请存储器空间时 存储管理