动态分区存储管理实验报告

时间:2024.4.20

数学计算机科学学院实验报告

专业名称  软件开发已应用 

实 验 室  学苑楼2#202   

实验课程  计算机操作系统 

  实验名称  动态分区存储管理

姓    名  ____ 杨剑_______

学    号  ___0915266______

同组人员  _____ 无________

实验日期  ____2011/5/23___

一、【实验目的】:

1、熟悉主存分配与回收

2、理解在不同的存储管理方式,如何实现主存空间的分配与回收

3、掌握动态分区分配方式中的数据结构和分配算法及动态分区存储管理方

式及其实现过程。

二、【实验内容和要求】:

主存的分配和回收的实现是与住存储器的管理方式有关的。所谓分配,就是解决多进程如何共享主存空间的问题。所谓回收,就是当进程运行完时将进程所占的主存空间归还给系统。

实验要求使用可变分区存储管理方式,分区分配中所用的数据就够采用空闲分区说明表和空闲分区链表来进行,分区分配中所用的算法采用首次适应算法、循环首次适应算法、最佳适应算法、三种算法来实现主存的分配与回收。

同时要求设计一个实用友好的可视化用户界面,并显示分配与回收过程。

三、【实验原理】

实验中为有效地对内存进行管理,实验中应设计一些数据结构,能有效地进行分配和回收,具体分析如下:

1、       设计一个空闲分区表,空闲分区表通过空闲分区链表来管理,在进行内存分配时,系统优先使用空闲分区低端的空间。

2、       设计一个内存分区表,可用链表管理,用以表示当前以内存使用情况。

3、       设计一个进程申请队列以及进程完成后的释放顺序,实现主存的分配和回收。

4、       要求每次分配和回收后把空闲分区的变化情况以及各进程的申请、释放情况以及各进程的申请、释放情况以图形方式显示、打印出来。

四、【实验环境】(使用的软件)

Microsoft Visual C++ 6.0

五、【实验设计分析】:

         内存分配:

①动态输入构造空闲区表,并显打印示构造好的空闲分区表。

②键盘接收内存申请。

③根据申请,实施内存分配,并返回分配所得内存首址。

④分配完后,调整空闲分区表(即扣除分配部分),并显示调整后的空闲分区表。

⑤若分配失败,返回分配失败信息。

内存回收:

①显示当前的空闲分区表和内存分区表。

②从键盘接收回收分区的首址与大小,按内存回收的四种情况进行内存回收。

③显示回收后已调整好的的空闲分区表

六、【实验过程和步骤】:

数据结构设计

①  空闲分区表的设计,该空闲分区表记录内存中未使用的各个分区,记录内容有未使用分区的大小、首地址,用链表就行管理;相关代码如下:

                   Typedef struct free

                     { 

                        Int size; //分区大小

                        Int address;//首地址

                        free *next;

};

②内存分区表设计,用以表示当前内存的使用情况,记录内容已使用分区的大小、首地址,用链表进行管理,相关数据结构如下:

                 Typedef struct map

                     { 

                        Int size; //分区大小

                        Int address;//首地址

                        map *next;

};

         ③进程申请队列的设计,用作进程到达的缓冲队列,记录各进程的相关信息,如进程的所需内存的大小、进程名,相关数据结构如下:

             Typedef struct pro

                     { 

                        Int size; //分区大小

                        sring name;

                        pro *next;

};

●  内存分配

当有进程进行内存申请时,我们利用首次适应算法从空闲分区链表、找出一块做够大的空间进行分配并对空闲分区和内存分区的相关结点进行处理,若未找到则返回错误信息,相关示意图如下:

●  内存回收

内存的回收存在以下几种情况:

         ①上邻空闲区:合并两分区,删除正回收的节点,改变上邻分区大小为两分区之和

②下邻空闲区:合并两分区,删除下邻分区节点,改变正回收节点大小为两分区之和,改变正回收节点的首址。

③上、下邻空闲区:合并三分区,删除下邻分区和正在回收节点,改变上分区节点大小为三分区之和,改变上分区收节点的首址

④不邻接,则建立一新表项。

             相关的示意图如下:

 

                

     ①                            ②                     ③

相关代码

1.采用最优分配算法分配作业空间,主要代码如下:

void allocate(char J,float xk)//采用最优分配算法分配xk大小的空间

{

   int i,k,l;

   float ad;

    k=-1;

    for(i=0;i<m;i++)    //寻找空间大于xk的最小空闲区登记项k

    if(free_table[i].length>=xk && free_table[i].flag==1)

       if(k==-1 || free_table[i].length<free_table[k].length)

          k=i;

    if(k==-1)    //未找到可用空闲区,返回

   {

       AfxMessageBox(“有效空间不足!”);

        return;

    }

    //找到可用空闲区,开始分配:若空闲区大小与要求分配的空间差小于minisize大小,则空闲区全部分配;若空闲区大小与要求分配的空间差大于minisize大小,则从空闲区划出一部分分配

    if(free_table[k].length-xk<=minisize)

   {

       free_table[k].flag=0;

       ad=free_table[k].address;

       xk=free_table[k].length;

    }

    else

    {

       free_table[k].length=free_table[k].length-xk;

        ad=free_table[k].address+free_table[k].length;

    }

    //修改已分配区表

   l=0;

   for(i=0;i<n;i++)

   {

      while(used_table[i].flag=='0'&&i<n)    //寻找空表目

     {   

        if(i>=n)    //无表目填写已分分区

       {

          AfxMessageBox("无表目填写已分分区错误!");//修正空闲区表  

          if(free_table[k].flag==0)    //前面找到的是整个空闲区

             free_table[k].flag=1;

          else    //前面找到的是某个空闲区的一部分

          {

          free_table[k].length=free_table[k].length+xk;

          return;

          }

       }

       else    //修改已分配区表

       {

           used_table[i].address=ad;

           used_table[i].length=xk;

           used_table[i].flag=J;

       }

        l=1;

     }

     if(l==1) break;

   }

   return;

}//主存分配函数结束

3. 作业的回收

bool reclaim(char J)//回收作业名为J的作业所占主存空间

{

   int i,k,j, s,t;

    float S,L;

    //寻找已分配区表中对应登记项

    s=0;

    while((used_table[s].flag!=J  || used_table[s].flag=='0')&&s<=n)

    {

      

       if(s>=n)    //在已分配区表中找不到名字为J的作业

       {

       AfxMessageBox("找不到该作业");

           return (false);

       }

       s++;

    }

       //修改已分配区表

       if(used_table[s].flag==J)

       {   used_table[s].flag='0';

           //取得归还分区的起始地址S和长度L

           S=used_table[s].address;

           L=used_table[s].length;   

      

           j=-1;k=-1;i=0;

           //寻找回收分区的上下邻空闲区,上邻表目k,下邻表目J

           while(i<m&&(j==-1||k==-1))

           {

              if(free_table[i].flag==1)

              {   if(free_table[i].address+free_table[i].length==S)k=i;//找    到上邻

                     if(free_table[i].address==S+L)

                         j=i;    //找到下邻

              }

               i++;

           }

           if(k!=-1)

               if(j!=-1)    //上邻空闲区,下邻空闲区,三项合并

{ free_table[k].length=free_table[j].length+free_table[k].length+L; free_table[j].flag=0;

              }

              else    //上邻空闲区,下邻非空闲区,与上邻合并

                   free_table[k].length=free_table[k].length+L;

           else

              if(j!=-1)    //上邻非空闲区,下邻为空闲区,与下邻合并

              {      free_table[j].address=S;

                  free_table[j].length=free_table[j].length+L;

              }

              else    //上下邻均为非空闲区,回收区域直接填入

              {    //在空闲区表中寻找空栏目

                  t=0;

                  while(free_table[t].flag==1 && t<=m)

                  {                

                     if(t>=m)    //空闲区表满,回收空间失败,将已分配区表复原

                     {

                 AfxMessageBox("主存空闲表没有空间,回收空间失!");

                         used_table[s].flag=J;

                         return (false);

                     }

                     t++;

                  }

                      free_table[t].address=S;

                      free_table[t].length=L;

                      free_table[t].flag=1;   

              }

       }

  return(true);

}//主存归还函数结束

                               

 

          

              ● 程序流程图

        

 

七、【测试数据和实验结果分析】:

假设初始状态下,可用的内存空间为400KB,并有下列的请求序列:

     (1)进程1申请130KB  (2)进程2申请60KB

     (3)进程3申请100KB  (4)进程2释放60KB

     (5)进程4申请200KB  (6)进程3释放100KB

     (7)进程1释放130KB  (8)进程5申请140KB

     (9)进程6申请60KB   (10)进程7申请50KB

     (11)进程6释放60KB

  

●  实验结果分析:

由测试数据知,首先进程1、2、3到达缓冲队列依次申请各自所需内存,对应着上图1,之后进程3、1依次释放,对应图2,从实验结果看,实验结果的正确性得到验证。

八、【实验心得】:

本实验极大的帮助我们理解了动态分区作业存储管理的实现过程。在对作业采用最优适应算法的同时,还外加代码弥补了最优适应算法会产生极小的零碎空闲区的弊端。在作业存储时,当前作业的起始地址=原空闲区起始地址+原空闲区偏移地址-当前作业的偏移地址;由此可知当前作业在空闲区内是从空闲区的高地址开始分配。在对作业回收时,作业临区的回收采用if、else语句及其嵌套语句,清楚合理的实现了4中情况下的作业回收。


第二篇:动态分区存储管理实例


动态分区存储管理实例

⒈ 实验内容

主存储器空间分配实验。

⒉ 实验目的

通过首次适应算法、最佳适应算法和最坏适应算法实现主存空间的分配,可以使读者可好地理解存储分配算法。

⒊ 实验题目

编写一段程序来模拟可变分区管理方法。要求能通过文件形式定义空闲区表;能随意输入作业及需要分配的空间;能分别使用首次适应算法、最佳适应算法和最坏适应算法对输入的作业进行空间分配;能显示系统空闲表和已分配空间表。

⒋ 实验提示

⑴可变分区方式是按作业需要的主存空间大小来分区。当装入一个作业时,首先要查看是否有足够的空闲空间来分配,若有则按指定的分配方式进行分配;否则作业不能装入。随着作业的装入和撤离主存空间被分为若干个大大小小的不连续的区间,为了表明各区间的状态可以用一个内存分区表如表7-13所示来表示。

表7-13 内存分区表

这样我们可以定义一个如下的结构表示内存分区信息。

typedef struct node

{

int start;                    //起始地址

int length;              //长度

char tag[20];             //标志

}job;

⑵可变分区的三种算法就是为作业分配主存空间的方法。

● 首次适应算法:在空闲区间中查询满足作业需要的空间,并将作业装入第一个满足条件的空间中去。

● 最佳适应算法:在空闲区间中查询满足作业需要的空间,并将作业装入满足条件的空闲空间中最小的一个空间中去。

● 最坏适应算法:在空闲区间中查询满足作业需要的空间,并将作业装入满足条件的空闲空间中最大的一个空间中去。

从三种算法的说明可以看出,分配空间的过程主要可以分两步:

       ● 查询所有满足作业需求的空间块。

       ● 按照指定的算法将作业装入空间块中。

⑶在操作的最初主存空间实际就是一个大的空闲区,不涉及到如何分配的问题。为直接模拟运行一段时间后主存中出现了多个空闲块的状态,题目要求从一个文件读入空闲区表。在这里我们可以设计一个空闲区表文件的结构为如表7-14所示:

表7-14 空闲区表

这样也可以方便地将空闲表一次读入程序中,而不必再一个个的输入。

⑷主要变量及函数说明如表7-15所示

表7-15 变量与函数说明表

⑸mem.txt文件内容如下:

20 32

52 8

60 120

180 331

⒌ 实例代码

//动态分区算法memory.c

//运行环境Redhad9.0 gcc 4.0

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#define MAXJOB 200          //定义存储数据最大值

typedef struct node               //内存块结构

{

int start;

int length;

char tag[20];

}job;

job frees[MAXJOB];  //定义空闲区表

int free_quantity;           //空闲区块数

job occupys[MAXJOB]; //定义已分配区表

int occupy_quantity;             //已分配区块数

 //初始化函数

void initial()

{

int i;

for(i=0;i<MAXJOB;i++){

   frees[i].start=-1;

   frees[i].length=0;

   strcpy(frees[i].tag,"free");              //定义所有块为空闲块

   occupys[i].start=-1;

   occupys[i].length=0;

   strcpy(occupys[i].tag,"");        //已分配块为0

}

free_quantity=0;                         

occupy_quantity=0;

}

//读数据函数,从文件中读入空闲表的设置

int readData()

{

FILE *fp;

char fname[20];

printf("请输入初始空闲表文件名:");       //输入空闲表文件的文件名

scanf("%s",&fname);

if((fp=fopen(fname,"r"))==NULL){

printf("错误,文件打不开,请检查文件名\n");

}

else{

  while(!feof(fp)){                                          //打开文件读入空闲表信息

   fscanf(fp,"%d %d",&frees[free_quantity].start,&frees[free_quantity].length);

   free_quantity++;

  }

 return 1;

}

return 0;

}

//排序空闲表

void sort()

{

int i,j,p;

for(i=0;i<free_quantity-1;i++){

   p=i;

   for(j=i+1;j<free_quantity;j++){

    if(frees[j].start<frees[p].start){

     p=j;

   }

  }

 if(p!=i){

  frees[free_quantity]=frees[i];

  frees[i]=frees[p];

  frees[p]=frees[free_quantity];

  }

}

}

//显示函数

void view()

{

int i;

printf("\n---------------------------\n");

printf("当前空闲表:\n");                          //显示空闲表

printf("起始地址\t长度\t状态\n");

for(i=0;i<free_quantity;i++){

       printf("%8d\t%4d\t%s\n",frees[i].start,frees[i].length,frees[i].tag);

}

printf("\n----------------------------\n");

printf("当前已分配表:\n");

printf("起始地址\t长度\t占用作业名\n");

for(i=0;i<occupy_quantity;i++){                 //显示已分配表

       printf("%8d\t%4d\t%s\n",occupys[i].start,occupys[i].length,occupys[i].tag);

}

getchar();

}

//最先适应分配算法

void earliest()

{

char job_name[10];

int job_length;

int i,j,flag,t;

printf("请输入新申请内存空间的作业名:");

scanf("%s",&job_name);

printf("请输入新申请内存空间的大小:");

scanf("%d",&job_length);

flag=0;

for(i=0;i<free_quantity;i++){                          //顺序查找满足条件的空间

  if(frees[i].length>=job_length){

    flag=1;

  }

}

if(flag==0){                                            //没找到满足的空间

printf("\n当前没有能满足你申请长度的空闲内存,请稍候再试\n");

}

else{                                                      //找到了满足的空间

  t=0;

  i=0;

  while(t==0){

   if(frees[i].length>=job_length){

     t=1;

   }

   i++;

  }

  i--;

  occupys[occupy_quantity].start=frees[i].start;                //分配满足条件的空间

  strcpy(occupys[occupy_quantity].tag,job_name);

  occupys[occupy_quantity].length=job_length;

  occupy_quantity++;

  if(frees[i].length>job_length){

   frees[i].start+=job_length;

   frees[i].length-=job_length;

  }

  else{

   for(j=i;j<free_quantity-1;j++){

    frees[j]=frees[j+1];

   }

   free_quantity--;

printf("内存空间成功!\n");

  }

}

}

//最优适应分配算法

void excellent()

{

char job_name[20];

int job_length;

int i,j,flag,t;

printf("请输入新申请内存空间的作业名:");

scanf("%s",&job_name);

printf("请输入新申请内存空间的大小:");

scanf("%d",&job_length);

flag=0;

for(i=0;i<free_quantity;i++){

   if(frees[i].length>=job_length){

    flag=1;

  }

}

if(flag==0){

printf("\n当前没有能满足你申请长度的空闲内存,请稍候再试\n");

}

else{

  t=0;

  i=0;

  while(t==0){

    if(frees[i].length>=job_length){

     t=1;

   }

   i++;

  }

  i--;

  for(j=0;j<free_quantity;j++){           //找到满足条件的最小空闲空间

    if((frees[j].length>=job_length)&&(frees[j].length<frees[i].length)){

      i=j;

    }

  }

  occupys[occupy_quantity].start=frees[i].start;  //分配空闲空间

  strcpy(occupys[occupy_quantity].tag,job_name);

  occupys[occupy_quantity].length=job_length;

  occupy_quantity++;

  if(frees[i].length>job_length){

   frees[i].start+=job_length;

   frees[i].length-=job_length;

  }

  else{

   for(j=i;j<free_quantity-1;j++){

    frees[j]=frees[j+1];

   }

   free_quantity--;

printf("内存空间成功!\n");

  }

}

}

//最坏适应算法

void worst()

{

char job_name[20];

int job_length;

int i,j,flag,t;

printf("请输入新申请内存空间的作业名:");

scanf("%s",&job_name);

printf("请输入新申请内存空间的大小:");

scanf("%d",&job_length);

flag=0;

for(i=0;i<free_quantity;i++){

  if(frees[i].length>=job_length){

   flag=1;

   }

}

if(flag==0){

printf("\n当前没有能满足你申请长度的空闲内存,请稍候再试\n");

}

else{

   t=0;

   i=0;

   while(t==0){

   if(frees[i].length>=job_length){

    t=1;

   }

   i++;

  }

  i--;

  for(j=0;j<free_quantity;j++){     //找到满足条件的最大空闲空间

    if((frees[j].length>=job_length)&&(frees[j].length>frees[i].length)){

      i=j;

    }

  }

  occupys[occupy_quantity].start=frees[i].start;   //分配空闲空间

  strcpy(occupys[occupy_quantity].tag,job_name);

  occupys[occupy_quantity].length=job_length;

  occupy_quantity++;

  if(frees[i].length>job_length){

    frees[i].start+=job_length;

    frees[i].length-=job_length;

  }

  else{

   for(j=i;j<free_quantity-1;j++){

    frees[j]=frees[j+1];

   }

   free_quantity--;

printf("内存空间成功!\n");

  }

}

}

//主函数

int main()

{

int flag=0;

int t=1;

int chioce=0;

initial();                      //初始化

flag=readData();          //读空闲表文件

while(flag==1){

  sort();                       //排序

//显示菜单

printf("\n=====================================\n");

printf("动态分区算法");

printf("\n=====================================\n");

printf("1.显示空闲表和分配表\n2.最先适应法  \n3.最优适应法 \n4.最坏适应法 \n0.退出\n=============");

printf("请选择:");

scanf("%d",&chioce);                       //输入选择的菜单项

switch(chioce){

  case 1:                             //显示空闲表和分配表

     view();

   break;

 

  case 2:                             //调用最先适应法

   earliest();

   break;

  case 3:                             //最优适应法

  excellent();

  break;

  case 4:                             //最坏适应法

  worst();

  break;

  case 0:                             //退出

   flag=0;

   break;

  default:

printf("\n选择错误!\n");

  }

}

}

运行结果:

[root@redlinux ys]# gcc memory.c –o memory.o

[root@redlinux ys]#./memory.o

请输入初始空闲表文件名:mem.txt↙

=====================================

动态分区算法

=====================================

1.显示空闲表和分配表

2.最先适应法

3.最优适应法

4.最坏适应法

0.退出

=============请选择:1↙

---------------------------

当前空闲表:

起始地址        长度    状态

      20          32    free

      52           8    free

      60         120    free

     180         331    free

----------------------------

当前已分配表:

起始地址        长度    占用作业名

选择2后,情况如下:(由于篇幅有限,简化了运行过程)

=============请选择:2↙

请输入新申请内存空间的作业名:a↙

请输入新申请内存空间的大小:32↙

内存空间成功!

=============请选择:2↙

请输入新申请内存空间的作业名:b↙

请输入新申请内存空间的大小:24↙

---------------------------

当前空闲表:

起始地址        长度    状态

      52           8    free

      84          96    free

     180         331    free

----------------------------

当前已分配表:

起始地址        长度    占用作业名

      20          32    a

      60          24    b

更多相关推荐:
存储管理实验报告

软件学院计算机课程实验报告册课程名称计算机操作系统实验学期20xx年至20xx年第2学期学生所在院系软件学院年级11软件专业班级软工1班学生姓名朱水云学号1115114034指导教师陈自刚实验最终成绩软件学院实...

操作系统存储管理实验报告

北京邮电大学操作系统实验实验报告实验日期20xx1220实验名称存储管理一实验目的2二实验内容2三实验分析2对于伙伴算法2对于虚拟存储区和内存工作区的不同算法3四编程实现3伙伴算法3原理3伙伴的概念3内存的释放...

《操作系统》存储管理实验报告

《操作系统》存储管理实验报告____大学____学院实验报告

存储管理实验报告

北方工业大学北方工业大学20xx513第2页共8页北方工业大学20xx513第3页共8页北方工业大学20xx513第4页共8页北方工业大学20xx513第5页共8页北方工业大学20xx513第6页共8页北方工业...

存储管理实验报告

实验四存储管理实验报告一实验目的存储管理的主要功能之一是合理地分配空间请求页式管理是一种常用的虚拟存储管理技术本实验的目的是通过请求页式管理中页面置换算法模拟设计了解虚拟存储技术的特点掌握请求页式存储管理的页面...

存储管理实验报告

GDOUB11112广东海洋大学学生实验报告书学生用表实验名称存储管理学院系学生姓名课程名称专业学号操作系统课程号班级实验日期软件学院软件工程实验地点一实验目的修改MINIX操作系统内存管理的源程序将MINIX...

存储管理实验报告

实验三存储管理一实验目的一个好的计算机系统不仅要有一个足够容量的存取速度高的稳定可靠的主存储器而且要能合理地分配和使用这些存储空间当用户提出申请存储器空间时存储管理必须根据申请者的要求按一定的策略分析主存空间的...

存储管理实验报告

实验三存储管理一实验目的一个好的计算机系统不仅要有一个足够容量的存取速度高的稳定可靠的主存储器而且要能合理地分配和使用这些存储空间当用户提出申请存储器空间时存储管理必须根据申请者的要求按一定的策略分析主存空间的...

存储管理的模拟实现实验报告

南昌大学实验报告5存储管理的模拟实现学生姓名学号专业班级实验类型验证综合设计创新实验日期实验成绩一实验目的存储管理的主要功能之一是合理地分配空间请求页式管理是一种常用的虚拟存储管理技术本实验的目的是通过请求页式...

操作系统-请求页式存储管理实验报告

操作系统实验三存储管理实验班级学号姓名目录1实验目的22实验内容21通过随机数产生一个指令序列共320条指令22将指令序列变换成为页地址流23计算并输出下述各种算法在不同内存容量下的命中率23随机数产生办法3环...

操作系统存储器管理实验报告.doc

操作系统原理实验报告1一目的与要求1请求页式虚存管理是常用的虚拟存储管理方案之一2通过请求页式虚存管理中对页面置换算法的模拟加深理解虚拟存储技术的特点3模拟页式虚拟存储管理中硬件的地址转换和缺页中断并用先进先出...

操作系统实验报告-存储管理实验

存储管理实验一实验目的及要求通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解熟悉虚存管理的各种页面淘汰算法通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解二实验环境操作系统Windows...

存储管理实验报告(53篇)